I am trying to implement AJAX in my to do type app, but am getting a missing template error (Missing template items/create, application/create with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee]}.) on my create action. There shouldn't be a create.html.erb page because the creation of items happens on a lists#show page:
<div class='new-item'>
<%= render 'items/form' %>
</div>
<div class="js-items">
<% #items.each do |item| %>
<%= div_for(item) do %>
<p><%= link_to "", list_item_path(#list, item), method: :delete, remote: true, class: 'glyphicon glyphicon-ok', style: "margin-right: 10px" %>
<%= item.name %>
<% if item.delegated_to != "" && item.user_id == current_user.id %>
<small>(Delegated to <%= item.delegated_to %>)</small>
<% elsif item.delegated_to != "" && item.user_id != current_user.id %>
<small>(Delegated by <%= item.user_id %>)</small>
<% end %></p>
<% end %>
<% end %>
</div>
And the _form.html.erb partial to which it links:
<div class="row">
<div class="col-xs-12">
<%= form_for [#list, #item], remote: true do |f| %>
<div class="form-group col-sm-6">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', placeholder: "Enter Item Name" %>
</div>
<div class="form-group col-sm-6">
<%= f.label 'Delegate To (Not Required)' %>
<%= f.text_field :delegated_to, class: 'form-control', placeholder: "Enter an Email Address" %>
</div>
<div class="text-center"><%= f.submit "Add Item to List", class: 'btn btn-primary' %></div>
<% end %>
</div>
</div>
Here's the create method in the items_controller:
def create
#list = List.friendly.find(params[:list_id])
#item = #list.items.new(item_params)
#item.user = current_user
#new_item = Item.new
if #item.save
flash[:notice] = "Item saved successfully."
else
flash[:alert] = "Item failed to save."
end
respond_to do |format| <<<<ERROR CALLED ON THIS LINE
format.html
format.js
end
end
And here's my create.js.erb file:
<% if #item.valid? %>
$('.js-items').prepend("<%= escape_javascript(render(#item)) %>");
$('.new-item').html("<%= escape_javascript(render partial: 'items/form', locals: { list: #list, item: #new_item }) %>");
<% else %>
$('.flash').prepend("<div class='alert alert-danger'><button type='button' class='close' data-dismiss='alert'>×</button><%= flash.now[:alert] %></div>");
$('.new-item').html("<%= escape_javascript(render partial: 'items/form', locals: { list: #list, item: #item }) %>");
<% end %>
Anyone have any ideas why I am getting this? I tried removing the format.html line from the items_controller but I got an unrecognizable format error.
You can force the form submission to use a JS format, instead of the default HTML format, so that your respond_to block will render the create.js.erb view instead of the create.html.erb view.
<%= form_for([#list, #item], format: :js, remote: true) do |f| %>
Typically, Rails will detect your remote: true option via "unobtrusive JavaScript (ujs)", which will effectively handle the format: :js option for you. There is something unique in your setup that we have not identified, which is requiring you to enforce the format option.
To see that your create.js.erb is working, you can change the line that renders your item partial:
$('.js-items').prepend("<%= escape_javascript(render(#item)) %>");
To render a the item's name, wrapped in a <p> tag:
$('.js-items').prepend("<p>" + <%= #item.name %> + "</p>");
You can customize that line to generate the html that you want to appear for your new list item. Based on your code above, this looks like it will work out for you.
As you finish your to-do app, you can create a partial for your item, and then change that line again so that your partial will be appended to your list of items.
Related
Im trying to implement a bit a Ajax into my app seems to work correctly but it isnt updating the page after the action is executed .
I added Ajax to my Destroy method
def destroy
#item = Item.find(params[:id])
#item.user = current_user
if #item.destroy
flash[:notice] = "Item Completed"
else
flash[:alert] = "Item was unable to be marked completed "
end
respond_to do |format|
format.html
format.js
end
end
i have update my _item.html.erb and _form.html.erb partials with remote: true
<%= content_tag :div, class: 'media', id: "item-#{item.id}" do %>
<div class="media">
<div class="media-body">
<small>
<%= item.name.titleize %>
| submitted <%= time_ago_in_words(item.created_at) %>
<% if current_user == #user %>
<%= link_to "Completed ", [#user, item], method: :delete,remote: true, class: 'glyphicon glyphicon-ok' %><br>
<% end %>
</small>
</div>
</div>
<% end %>
_from.html.erb
<%= form_for [#user, item ], remote: true do |f|%>
<div class="form-group">
<%= f.label :name, class: 'sr-only' %>
<%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
</div>
<%= f.submit "Submit Item", class: 'btn btn-primary pull-right' %>
<% end %>
User#show view <div class='new_item'>
<%= render :partial => 'items/form', :locals =>{:item => Item.new} %>
</div>
<% end %>
<div class='js-items'>
<% #user.items.order('created_at DESC').each do |item| %>
<%= render :partial => 'items/item' , :locals => {:item => item } %>
</div>
destroy.js.erb
$('#item-<%= #item.id %>').hide();
Like I said before, the item is deleted when i click the delete button but i need to refresh the page in order to see the updated page. Any ideas what i might be doing wrong, any push to the right direction would be greatly appreciated!
Try rendering the java script in the method itself and check,
def destroy
#item = Item.find(params[:id])
#item.user = current_user
if #item.destroy
flash[:notice] = "Item Completed"
else
flash[:alert] = "Item was unable to be marked completed "
end
respond_to do |format|
format.html
format.js { render
$('#item-<%= #item.id %>').hide();
}
end
end
I'm trying to add a form to a modal and then submit the form via JS format with remote: true but the form seems to be submitted as HTML instead, causing an unknown format issue. Any help would be appreciated.
Started POST "/create_deliv_extra" for 127.0.0.1 at 2014-06-16 20:38:17 -0400
Processing by DeliveriesController#create_deliv_extra as HTML
Completed 406 Not Acceptable in 21ms
ActionController::UnknownFormat
Form:
</br>
<%= form_tag create_deliv_extra_url, remote: true, class:"form-inline mb10 mt5", id:"extra_f_#{order.id}" do %>
<%= text_field_tag :description, #extra.description, placeholder: "Description", "data-provide"=>"typeahead", autocomplete: :off, "data-source"=>"#{Extra.all.pluck(:description).uniq}", class:"span4" %>
<% if order.cod == true || current_user.role == "Billing" || current_user.role == "admin" || current_user.role == "Exec" %>
<div class="input-prepend">
<span class="add-on">Amount $</span>
<%= text_field_tag :amount, #extra.amount, placeholder: "$000.00", class:"input-xs" %>
</div>
<% end %>
<div class="input-prepend">
<span class="add-on">Quantity</span>
<%= text_field_tag :quantity, #extra.quantity.present? ? "%g" % #extra.quantity : 1, class:"input-xxs" %>
</div>
<% next_d = order.deliveries.present? ? order.deliveries.maximum(:delivery_counter) + 1 : 1 %>
<div class="input-prepend">
<span class="add-on">From</span>
<%= text_field_tag :load_start, next_d, class:"input-xxxs" %>
</div>
<div class="input-prepend">
<span class="add-on">To</span>
<%= text_field_tag :load_end, next_d, class:"input-xxxs" %>
</div>
<%= select_tag :extra_type, options_for_select(["Per Yard","Per Load","Flat Fee"], #extra.extra_type), class:"input-small" %>
<%= hidden_field_tag :order_id, order.id %>
<%= hidden_field_tag :truck_id, #id %>
<%= button_tag "Add", class:"btn btn-danger" %>
<% end %>
Controller:
def create_deliv_extra
#order = Order.find(params[:order_id])
#id = params[:truck_id]
#extra = Extra.create(amount: params[:amount], extra_type: params[:extra_type], order_id: params[:order_id], description: params[:description], quantity: params[:quantity], load_start: params[:load_start], load_end: params[:load_end])
#extras = #order.next_deliv_extras.length > 1 ? "Extras: " + #order.next_deliv_extras : "No Extras"
respond_to do |format|
format.js
end
end
I've also tried adding format: :js in the form_tag but still receive the same error.
I know the question is old, but I got the same problem and found out my application.js was not requiring jquery_ujs. I added it to my application.js file:
//=require jquery
//=require jquery_ujs
Now remote links and forms work as expected :)
I believe your problem may stem from a form_tag being with another form (form_tag, form_for, or html form). If this is the case, just find a way within the html for the first form to begin and end and then start the second form after the first ends.
<%= form_for do %>
...
<%= button_tag "#" %>
<% end %>
<%= form_tag create_deliv_extra_url, remote: true, class:"form-inline mb10 mt5", id:"extra_f_#{order.id}" do %>
...
<%= button_tag "Add", class:"btn btn-danger" %>
<% end %>
TLDR: Trying to add a follow/unfollow button to the Users#Index action but when clicking on the button nothing happens.
I have followed Michael Hartl's Rails Tutorial app and now that it's complete I want to add extra functionality for the Follow/Unfollow button. Currently, you can only follow/unfollow a user after visiting their profile page thru the Users Show action. I've attempted to expand this functionality to the Index page of the Users controller so that instead of having to visit each user's profile page in order to follow/unfollow them, a follow button will also appear next to their name in the Index view.
The code that works initially for the follow/unfollow button on the Users Show action:
users_controller.rb
https://gist.github.com/anonymous/9602598
show.htlm.erb for users view
https://gist.github.com/anonymous/9602616
_follow_form.htlm.erb partial for users view
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
_follow.html.erb partial for users view
<%= form_for(current_user.relationships.build(followed_id: #user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
_unfollow.html.erb partial for users view
<%= form_for(current_user.relationships.find_by(followed_id: #user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
create.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
index.html.erb inside of the users view
<%= render #users %>
_user.html.erb partial inside of users view
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
I've tried a few different approaches that so far have been fruitless
First I tried simply rendering the follow_form partial inside of the _user partial just like it's done for the User Show view
_user.html.erb partial inside of users view
<%= render 'follow_form' if signed_in? %>
this resulted in the following error: NoMethodError in Users#index "undefined method `id' for nil:NilClass" and it hilights the following line of code inside of the follow_form partial
<% if current_user.following?(#user) %>
After mucking around with the variables and the controller for a few hours I finally managed to get the buttons to show properly on the index page with the following code inside of the _user.html.erb partial
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(#current_user.relationships.find_by(followed_id: #users),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: #users),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
This code however, only shows the correct follow/unfollow buttons for each user but when you click a button nothing happens. I also attempted to edit the JS files with the following code
create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#user").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#user").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
This didn't have any effect.
The more I tinker with different parts of the code the more it's confusing me. Here is my relationships controller for good measure.
relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :signed_in_user
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
I know it's alot but if anyone can help shed some light on my situation I would be very grateful. This is my first venture outside of tutorials and I figured it would be a good idea to try and add features to an already working project instead of start something from scratch.
Just in case anybody was on this question and was still looking for the correct Ajax code. This works with the existing controller and nothing else will have to be changed.
create.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/unfollow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
destory.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/follow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
_user.html.erb
<div class="col-md-2">
<% unless current_user?(user) %>
<% form_id = user.id.to_s %>
<div id="follow_form_<%= form_id %>">
<% if current_user.following?(user) %>
<%= form_for(current_user.active_relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
<% else %>
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
<% end %>
</div>
This is my first post. Yay! Hope it helps someone!
Use the following code in _user.html.erb partial:
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(current_user.relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
I made couple of changes to the code in form_for method call in 2 places:
#current_user should be current_user.
Secondly, followed_id: #users should be followed_id: user.id
I'm trying to create a nested form where there is a "+" button which adds fields via jquery and ajax. I am doing it adding a step at once, so untill now I am able to add a simple text pushing the "+" button, but, as I have just said, I want to add some fields.
I have the followings:
new.html.erb
<h1>New Campaign</h1>
<%= form_for #campaign, html: { multipart: true } do |f| %>
....
<div class="goods">
<%= render "goods/good", f: f, child_index: Time.now.to_i %>
</div>
<div class="actions">
<%= link_to '+', add_good_row_path(params[:campaign]=#campaign, params[:f] = f), remote: true, class: 'btn btn-large btn-success' %>
<%= f.submit 'Crea', class: 'btn btn-large btn-warning' %>
</div>
<% end %>
goods/_good.html.erb
<%= f.fields_for :goods, #campaign.goods.build, child_index: child_index do |good| %>
<%= good.text_field :name, placeholder: 'Nome' %>
<%= good.text_area :description, placeholder: 'Descrizione' %>
<%= good.text_field :cost, placeholder: 'Costo' %>
<% end %>
campaigns_controller.rb
class CampaignsController < ApplicationController
....
def add_good_row
respond_to do |format|
format.js
end
end
end
add_good_row.js.erb
$('.goods').append("hello");
I think that I understood the problem, it is to pass a f variable, a #campaign variable and a child_index to the partial, but how can I do that via jquery?
Hope I was clear...
Have a look at this gem.
I think it's what you are looking for
https://github.com/nathanvda/cocoon
I'm using an inline form for users to submit data to a table (note that I'm using CSS rather than html tables to achieve this). When an error is returned by the verification in the model, I want to highlight the input field using the Bootstrap error class and put the error message below the appropriate form field. I'm using AJAX to submit the form.
I'm having problems, this is what I have so far:
Controller:
def create
#travel = Travel.new(params[:travel])
#travel[:user_id] = current_user.id
convert_date # and return
if #travel.save
flash[:notice] = "Successfully saved trip"
#travels = Travel.where("user_id = ?",current_user)
respond_to { |format| format.js }
end
end
JS view:
<% if #travel.errors.any? %>
<% #travel.errors.full_messages.each { |msg| logger.debug(msg) } %>
<% #travel.errors.messages.each do |k,v| %>
<% logger.debug("#tf_#{k}") %>
$(<%= "#tf_#{k}" %>).insertAdjacentHTML("afterbegin","<span class="control-group error"><span class="controls">");
$(<%= "#tf_#{k}" %>).insertAdjacentHTML("beforeend","</span></span>");
$(<%= "#error_#{k}" %>).val("<%= "#{k} #{v}" %>");
<% end %>
<% else %>
$(":input:not(input[type=submit])").val("");
$("#travels_list").html("<%= escape_javascript( render(:partial => "travels") ) %>");
<% end %>
form partial:
<%= form_for #travel, :remote => true, :html => {:class => "form-inline", :id => "new-travel-form"} do |f| %>
<div class="row-fluid">
<span id="tf_city"><%= f.text_field :city, :placeholder => "London, UK", :class => "span3" %></span>
<span id="tf_arrive_date"><%= f.text_field :arrive_date, :class => "span2" %> </span>
<span id="tf_leave_date"><%= f.text_field :leave_date, :class => "span2" %> </span>
<span id="tf_notes"><%= f.text_field :notes, :placeholder => "e.g. staying at the Hilton", :class => "span3" %></span>
<%= f.submit "save", :class => "btn btn-primary span1" %>
</div>
<% end %>
<div class="row-fluid error" id="error_expl">
<span id="error_city" class="help-inline span3"></span>
<span id="error_arrive_date" class="help-inline span2"></span>
<span id="error_leave_date" class="help-inline span2"></span>
<span id="error_notes" class="help-inline span3">test</span>
</div>
The logger.debug in the JS is firing, so I know that the error is getting passed to the JS, but the insertAdjacentHMTL() doesn't seem to be working.
maybe this is not going to answer your question but i hope it could help to improve your code.
First, according to your code i guess you should have some associations like this in the model User:
has_many :travels
And in your model Travel:
belongs_to :user
So, in order to improve your code you can have this in your controller:
respond_to :js, only: [:create]
def new
#travel = current_user.travels.new
end
def create
#travel = current_user.travels.new(params[:travel])
if #travel.save
flash[:notice] = "Successfully saved trip"
#travels = current_user.travels
else
# I guess you should have some code here in case any validation fail. If you dont
# have validations for the model Travel, you don't need the if statement here.
end
end
About your problem, can you clarify what is "#tf_#{k}"?