Ruby on Rails: error when using unobtrusive JavaScript to update partial - javascript

I am using Rails 3.2.13, and I'm trying to update a 'summary' partial after creating a 'child' item.
I have a template and template tasks, and what I am trying to do is update the partial on the 'show' view, which is a summary that indicates how many tasks are allocated to the template. I am doing this in the create.js.erb of the template task.
Here are the contents of _template-summary.html.erb:
<div id="template-summary-details">
<table class="table table-striped">
<tbody>
<tr>
<td><span class="fa fa-th-list"></span> No. of tasks</td>
<td><%= #template.templatetasks.count %></td>
</tr>
<tr>
<td><span class="fa fa-clock-o"></span> Total task days</td>
<td>
<%= #template.templatetasks.sum(:days) %>
</td>
</tr>
<tr>
<td><span class="fa fa-check-square-o"></span> No. of checklists</td>
<td>
<%= #template.templatetasks.count(:checklist_id) %>
</td>
</tr>
</tbody>
</table>
</div>
And here are the contents of create.js.erb:
<% #template = Template.where("id = ?", #templatetask.template_id?) %>
$("#template-summary-details").replaceWith("<%= escape_javascript(render partial: "templates/template-summary", locals: {template: #template}) %>");
<% if #templatetask.parent_id? %>
$('#templatetasks'+<%= #templatetask.parent_id %>).prepend('<%= j render(#templatetask) %>');
<% else %>
$('#templatetasks').prepend('<%= j render(#templatetask) %>');
<% end %>
The problem is that I am getting the following error:
undefined method `where' for ActionView::Template:Class
I have also tried using find but haven't gotten that to work either.
How else would I pass the #template to the partial during the creation of a template task?

You first problem is that you have a name clash between the Rails class ActionView::Template and your Template model class. You can work around that by referring to your model class as ::Template (a top-level Ruby class). e.g.
<% #template = ::Template.where("id = ?", #templatetask.template_id).first %>
But that is just a round about way of doing a primary key lookup which is simpler with find:
<% #template = ::Template.find(#templatetask.template_id) %>
Even easier, if you have already set up a belongs_to association from TemplateTask to Template you could just refer to the related object directly:
<% #template = #templatetask.template %>
That would probably get you a bit further but if you want to make your partials more reusable its might be better to avoid having them refer to instance variables (e.g. #template). Instead the partial should refer to a local template variable that you pass into the render method via the locals hash (which you are already doing).

Related

How to display multiple JSON objects in an ejs tag

I am making a table using NodeJS/JS/HTML/CSS/EJS. I want the table to be able to show to JSON objects in one column. When I use the code below, it runs fine, but it only prints out the second object given, not both.
Example: I am trying to print out the first and last name on one line, but it only shows the last name on the page (I'm assuming it's writing the firstName, but then overwriting it with the lastName.)
<div>
<table>
<% data2.forEach(function(person) {%>
<tr><td id="<%= person["ID"]%>"><%= person["firstName", "lastName"] %>
<% }); %></td></tr>
</table>
Figured it out for all who our interested in the future... Simple mistake
<div>
<table>
<% data2.forEach(function(person) {%>
<tr><td id="<%= person["ID"]%>"><%= person["firstName"] %> <%= person["lastName"] %>
<% }); %></td></tr>
</table>
</div>

Rails 4: dynamically added checkboxes are not submitting

I started to learn Rails and try to apply AJAX with some records that are added dynamically in a listing. Then I want to delete multiple records that are selected via checkboxes directly in the listing.
It works fine but not when I create a new Record and want to delete it without refreshing the page. The header's response is : "ActiveRecord::RecordNotFound in AccountsController#destroym". It acts as if I click the button without checking my checkboxes.
Thanks for your help :)
accounts_controller.rb
def destroym
Account.destroy(params[:delete])
respond_to do |format|
format.html {redirect_to accounts_path}
format.js #render accounts/destroym.js.erb
end
end
_row.html.erb
<% #data = Account.find(id) %>
<tr id='tr<%= #data.id %>'>
<td><%= #data.id %></td>
<td><%= #data.login %></td>
<td><%= check_box_tag 'delete[]', #data.id %></td>
</tr>
index.html.erb
<table class="table table-striped table-hover " id="accountsListing">
<%= form_tag destroym_accounts_path, method: :DELETE, remote: true, id: "deleteForm" do %>
<thead>
<tr>
<th>#</th>
<th>Username</th>
<th>Password</th>
<th>Website</th>
<th>Date</th>
<th>Editer</th>
<th><%= submit_tag "delete" %>
<%= link_to "Delete", '', :onclick => "$('#deleteForm').submit()", id: "removePwd", class: "text-danger", remote: true, method: :DELETE %> </th>
</tr>
</thead>
<tbody>
<% #accounts.each do |account| %>
<%= render 'row', id: account.id %>
<% end %>
</tbody>
<% end %>
</table>
destroym.js.erb
$("#accountsListing input:checked").closest("tr").remove();
create.js.erb
$("#accountsListing tr:first").after("<%= escape_javascript (render 'row', id:#account.id) %>");
The problem in this case is that you're replacing your whole page's HTML... So, all the DOM events bound to your elements are also destroyed.
When you replace your html (the .js.erb file), Rails will provide some special attributes to your elements (Rails calls that "unobstrusive JavaScript", because there's no JS code directly in your elements).
The issue here, of course, is that the JS code that Rails uses (see my link) are only applied when the page launches.
You have several choices:
1) your destroy.js.erb can only remove the exact row you just deleted (instead of replacing all the rows).
2) you can call rails-ujs' code by yourself. This is a hack and should not seriously be considered.
3) you can reload the page "automatically" (you lose the benefit of AJaX).
4) you can write your own JS code to send the AJaX request.
My solution to handle checkboxes created dynamically. The on function is mandatory if you want to handle events on elements added dynamically.
JS code
$("#deleteBtn").on("click", function() {
var ids = [];
$('#accountsListing :checkbox:checked').each(function(){
ids.push($(this).val());
});
$.ajax({
url: '/accounts/destroym',
type: 'POST',
data: {
"_method":"DELETE",
"authenticity_token": window._token,
"delete[]": ids
},
});
});

How to asynchronously send JS variable to Rails

Simple HTML form in a view. I need the user selected value of the form to pass into the active record query when the user switches it. (Probably not params because then it won't be asynchronous?)
In the example below I need the business_id to be the value of the form. New to rails, so if you could provide some in page javascript, I'll deal with refactoring it to the resources later...
<select name="clients">
<option value="1">Tesla</option>
<option value="4">Chevy</option>
</select>
<table>
<% #clients.where(month_year:'2015-02',business_id:'NEED VALUE OF HTML FORM HERE').find_each do |client| %>
<tr>
<td><%= client.month_year %></td>
<td><%= client.business_id %></td>
<td><%= client.bill_charge %></td>
</tr>
<% end %>
</table>
To expound on other answers, here's a (perhaps) overly simplified mock up.
Client view
Here you need to call render that points to a partial. This partial will contain the table data (so it's resuable later). You also need to give your select statement a class that jquery can easily grab to do the async fetch of your client data.
# app/views/clients/index.html.erb
<%= select_tag "business", options_from_collection_for_select(Business.all, "id", "name"), class: "car-select" %>
<div class="clients-table">
<%= render "table_list" %>
</div>
Table Partial
With the table you just cut out of the index view, you'll need to paste into a partial
# app/views/clients/_table_list.html.erb
<table>
<thead>
<tr>
<th>Month year</th>
<th>Business</th>
<th>Bill charge</th>
</tr>
</thead>
<tbody>
<% #clients.each do |client| %>
<tr>
<td><%= client.month_year %></td>
<td><%= client.business.try(:name) %></td>
<td><%= client.bill_charge %></td>
</tr>
<% end %>
</tbody>
</table>
AJAX script
This need to watch for changes to the select and submit a request for client data
# app/assets/javascripts/clients.coffee
ready = ->
$('.car-select').on 'change', ->
bid = $(this).val()
$.ajax
url: '/businesses/' + bid
dataType: 'script'
return
return
$(document).ready(ready)
$(document).on('page:load', ready)
# this is turbolinks-friendly
Businesses Controller processes request
In your ajax request you are calling to a URL like, "http://yourapp.com/businesses/23", which really hits the show action of your businesses controller. You want to do it this way because it's completely RESTful and you don't have to change any routes. But you will need to edit the action to provide an instance variable for clients.
# app/controllers/businesses_controller.rb
def show
#business = Business.find(params[:id])
#clients = #business.clients (this assumes that you already have a proper has_many / belongs_to relationship between business and client)
respond_to do |format|
format.html
format.js
end
end
UJS View
The last piece of the puzzle is the UJS view. This is javascript that is only called when the js request type is sent to a particular controller action. In this case, the show action of the businesses controller. This is going to take the newly created #clients and replace the existing table with the partial and new data.
#app/views/businesses/show.js.erb
$(".clients-table").html("<%= escape_javascript(render( '/clients/table_list', client: #clients)) %>");
If you still have questions, or want to do more complicated things, you should go research a little on UJS templates and callbacks.
put your result table into a partial.
fire a ajax request on the on change event of the select
render the table based on the value of the select which you pass as request variable (`#clients')

Express.js to EJS rendering data partially

Imagine the Database like below.
// 'Article' Schema
{
subject : 'Hello world',
content : 'I want to display this content partially.
The content would has verbose text like long
blabla...........blabla.......blabla......blabla...........
blabla.......blabla......blabla...........b........
and even more, It would has <img src=".......jpg"/>
}
Now I render this data to some ejs file,
<table>
<% Articles.forEach(function(article, index){ %>
<tr>
<td> <%= article.subject %> </td>
<td> <%= article.content %> </td>
</tr>
<% }) %>
</table>
// To don't display verbosely, give style attribute (Of course, on top of html)
<style>
td { white-space: nowrap; overflow: hidden; }
</style>
But this way, It maybe decrease application performance, right? If there are 10, 20, 30 articles on one page, The server will try to display whole of this things. What I want to make is some summary of contents, How can I do this cleverly?
For summery contents,display initial few text with ellipses in the end
<table>
<% Articles.forEach(function(article, index){ %>
<tr>
<td> <%= article.subject %> </td>
<td> <%= article.content.substring(0,10) %> ...</td>
<td> <a id="read_more" content_id="cont-id" href = "javascript:(void)"> read more..</a></td>
</tr>
<% }) %>
Then use ajax application to get complete data on click of read more depend whether are you using jquery or angular etc.
And if there are more article then do pagination with ajax application or page refresh
On node side create API which gives this content data or new articles in the same format that you did during page load

Static HTML, want to use ruby on rails

I have an app that hosts a static HTML webpage with text and some images. I want to use ruby on rails to learn about it more.
I have a simple ror app. I went to app/views/home.html.erb, and pasted the HTML I have there. This is not the best approach.
Is there a better approach to port this Static HTML to ror?
Where do javascript files go in ror?
You should checkout high_voltage, which is a gem for static pages.
1) You have helpers in RoR ERB to help you with HTML, especially if you connect to a DB, for example from their help:
<table>
<tr>
<th>Title</th>
<th>Summary</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #books.each do |book| %>
<tr>
<td><%= book.title %></td>
<td><%= book.content %></td>
<td><%= link_to "Show", book %></td>
<td><%= link_to "Edit", edit_book_path(book) %></td>
<td><%= link_to "Remove", book, method: :delete, data: { confirm: "Are you sure?" } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to "New book", new_book_path %>
Everything between <%= .... %> are RoR helpers, so it's really up to your application if RoR will help you with your static HTML or not (maybe since you say it's static, i.e. not dynamic at all, the best approach would just be to leave it as is.
2) Javascript files are placed under app/assets, and you should definitely read about the asset pipeline

Categories