I am trying to create a timeline where a user can create events to go on the timeline. I've had this working fine in the past, but have since updated my version of Rails to 3.2.14, and it no longer works. Could this possibly be a syntactical error if something has changed between versions, or have I done something wrong?
The timeline show view renders partials including the timeline, and create/edit/destroy form partials for the events. As I understand it, the form is getting submitted, and should be calling create.js.erb.
What is actually happening is that when I click 'create event', the contents of the page are simply replaced by the standard "Event was successfully created" notice (not the one from the create.js.erb), and everything else disappears. The event has been created though. Can anyone help?
timeline show view:
<div id="show-timeline">
<%= render :partial => "show_timeline" %>
</div>
<div class="content-box timeline-box">
<div id="my-timeline-box">
<%= render :partial => "my_timeline" %>
</div>
<br />
<button id="new-event-button" class="btn btn-success btn-large">New Event</button>
<button id="edit-events-button" class="btn btn-info btn-large">Edit Events</button>
<button id="delete-events-button" class="btn btn-danger btn-large">Delete Events</button>
<div id="events-forms">
<div id="new-event">
<%= render :partial => "new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) }, :remote => true %>
</div>
<div id="edit-events">
<%= render :partial => "edit_events", :locals => { :events => current_user.events }, :remote => true %>
</div>
<div id="delete_events">
<%= render :partial => "delete_events", :locals => { :events => current_user.events } %>
</div>
</div>
<div id="events-forms-edit"> </div>
</div>
events/create.js.erb
$('#new-event').html('<%= escape_javascript( render :partial => "/timelines/new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) }, :remote => true ) %>');
$('.notice').html("<p>Event was successfully created.</p>");
$('.notice').show(300);
$('#my-timeline-box').html('<%= escape_javascript( render :partial => "/timelines/my_timeline" ) %>');
$('#show-timeline').html('<%= escape_javascript( render :partial => "/timelines/show_timeline" ) %>');
$('#edit-events').html('<%= escape_javascript( render :partial => "/timelines/edit_events", :locals => { :events => current_user.events }, :remote => true ) %>');
$('#delete_events').html('<%= escape_javascript( render :partial => "/timelines/delete_events", :locals => { :events => current_user.events } ) %>');
events controller create action:
def create
#event = Event.new(params[:event])
#timeline = current_user.timeline
respond_to do |format|
if #event.save
format.html { redirect_to #event.timeline, notice: 'Event was successfully created.' }
format.json { render json: #event, status: :created, location: #event }
format.js
else
format.html { render action: "new" }
format.json { render json: #event.errors, status: :unprocessable_entity }
format.js
end
end
end
Any help would be much appreciated!
Update:
_new_event.html.erb
<br />
<h2>Add an event</h2>
<h4>Fill in the form and click 'Create Event' to add a new event to the timeline.</h4>
<%= form_for(event, :remote => true) do |f| %>
<% if event.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(event.errors.count, "error") %> prohibited this event from being saved:</h2>
<ul>
<% event.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%=f.hidden_field 'timeline_id', :value => current_user.timeline.id %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :start_date, :order => [:day, :month, :year], :start_year => 1800 %>
</div>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :headline, :size => 50 %>
</div>
<div class="field">
<%= f.label :event_description %><br />
<%= f.text_area :text, :size => "47x4" %>
</div>
<%= check_box_tag "blockCheck", :value => "1", :checked => false %>
<div class="field" id="media_box">
<%= f.label :media %> <span>Please paste a URL here</span><br />
<%= f.text_field :media, :size => 50 %>
</div>
<div class="field">
<%= f.label :media_description %><br />
<%= f.text_area :caption, :size => "47x3" %>
</div>
<div class="actions">
<%= f.submit 'Create Event', :class => "btn btn-success" %>
</div>
<% end %>
console output (when "Create Event" is clicked):
Started POST "/events" for 127.0.0.1 at 2013-08-07 15:07:03 +0100
Processing by EventsController#create as JS
Parameters: {"utf8"=>"V", "authenticity_token"=>"ppQnTSwha1veoTzAenrtl7uhtQ8wC
F6c2/AZMDGA/UE=", "event"=>{"timeline_id"=>"4", "start_date(3i)"=>"7", "start_da
te(2i)"=>"8", "start_date(1i)"=>"2013", "headline"=>"", "text"=>"", "media"=>"",
"caption"=>""}, "commit"=>"Create Event"}
←[1m←[36mUser Load (5.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users
"."id" = 2 LIMIT 1←[0m
←[1m←[35mTimeline Load (15.0ms)←[0m SELECT "timelines".* FROM "timelines" WHE
RE "timelines"."id" = 4 LIMIT 1
←[1m←[36mTimeline Load (38.0ms)←[0m ←[1mSELECT "timelines".* FROM "timelines"
WHERE "timelines"."user_id" = 2 LIMIT 1←[0m
←[1m←[35m (0.0ms)←[0m begin transaction
←[1m←[36mSQL (6.0ms)←[0m ←[1mINSERT INTO "events" ("caption", "created_at", "
credit", "end_date", "headline", "media", "start_date", "text", "thumbnail", "ti
meline_id", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)←[0m [["capti
on", ""], ["created_at", Wed, 07 Aug 2013 14:07:04 UTC +00:00], ["credit", nil],
["end_date", nil], ["headline", ""], ["media", ""], ["start_date", Wed, 07 Aug
2013], ["text", ""], ["thumbnail", nil], ["timeline_id", 4], ["updated_at", Wed,
07 Aug 2013 14:07:04 UTC +00:00]]
←[1m←[35m (171.0ms)←[0m commit transaction
Rendered timelines/_new_event.html.erb (15.0ms)
Rendered timelines/_my_timeline.html.erb (0.0ms)
Rendered timelines/_show_timeline.html.erb (0.0ms)
←[1m←[36mEvent Load (30.0ms)←[0m ←[1mSELECT "events".* FROM "events" INNER JO
IN "timelines" ON "events"."timeline_id" = "timelines"."id" WHERE "timelines"."u
ser_id" = 2←[0m
Rendered timelines/_edit_events.html.erb (41.0ms)
Rendered timelines/_delete_events.html.erb (3.0ms)
Rendered events/create.js.erb (5123.3ms)
Completed 200 OK in 7899ms (Views: 7538.4ms | ActiveRecord: 265.0ms)
However, nothing is getting rendered.
Check if you have the following lines in the top of your application.js.coffee:
#= require jquery
#= require jquery_ujs
If you're not using coffee, the lines should be the same but starting with //=.
It seems like you're not requiring Rails Unobtrusive Javascript library, so your form post is treated as HTML instead of JS.
If you do have this dependency covered, could you also provide the code for the javascript files related to this issue?
Related
I wish to reload a partial-form with a button(Add). I'm new and don't know how to simply display fields in partial like listings one under the other as many times Add button is clicked. I can't find a relevant example. all AJAX examples mention js.erb when object is saved in DB.
<div class="panel-body">
<%= render partial: "degrees/form", :locals => { :f => f } %>
<%= f.link_to (fa_icon 'plus').to_s + " Add Another Qualification ", render(:partial => 'degrees/form', :locals => { :f => f }), class: "btn btn-primary" %>
</div>
Here, #application is the main form trying to display degree fields. Partial is simply two text-fields- one for selecting educational degree and second its detail.Here's partial
<%= f.fields_for [Degree.new], :url => { :action => "index" } do |ff| %>
<div class = "form-group" }>
<%= ff.select :level, options_for_select(Job::EDUCATION, params[:level]), include_blank: "Select Degree", class: 'span-2' %>
<%= ff.text_field :description, :class => 'span5' %>
</div>
<% ff.submit "Add Another Degree", class: 'btn btn-primary' %>
You don't necessary need to save things to pass away to .js.erb... you can just instantiate...
But if your example is precise, you are missing the remote: true flag for the link... And the partial is not defined on the link... you need to make a view responding to the ajax...
Form example
<div class="panel-body">
<%= link_to new_thing_path, remote: true do %>
<i class="fa fa-plus">
Add another qualification
<% end %>
<div class="new-things-container">
</div>
</div>
Controller answering to the ajax request
class ThingsController < ApplicationController
def new
#thing = Thing.new
respond_with #thing
end
end
View for the ajax request rendering a partial inside a specified div
//views/things/new.js.erb
$('.panel-body .new-things-controller').append("<%= render partial: 'degrees/form', locals: { thing: #thing } %>")
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.
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
This is a simple grocery list app. Left column div is a list of lists. Items for a particular list are displayed in the right column div.
Here's the process:
A user clicks on one of the lists, which then loads (AJAX) it's related items in the right div. This is working fine.
Here's where I'm stuck:
Above the items is an input field to submit a new item to the list of items below. I want AJAX to add the new item to the items below but when I press enter on the form field, nothing happens. When I refresh, the new item is added.
Here's what the server said:
Processing by ItemsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"YWIlMPXqoTvhqzGGPqm6Rn/E7jPRt8do/2tkjd0H1Qk=", "item"=>{"name"=>"Mayo"}, "list_id"=>"4"}
List Load (0.1ms) SELECT "lists".* FROM "lists" WHERE "lists"."id" = ? LIMIT 1 [["id", "4"]]
(0.0ms) begin transaction
SQL (20.9ms) INSERT INTO "items" ("completed", "created_at", "description", "list_id", "name", "position", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["completed", false], ["created_at", Mon, 29 Apr 2013 21:59:06 UTC +00:00], ["description", nil], ["list_id", 4], ["name", "Mayo"], ["position", nil], ["updated_at", Mon, 29 Apr 2013 21:59:06 UTC +00:00]]
(1.6ms) commit transaction
Rendered items/_piece.html.erb (0.0ms)
Rendered items/create.js.erb (0.7ms)
Here's the page loading process:
home.html.erb > _single.html.erb > create.js.erb > adds _piece.html.erb to home.html.erb
This is the Create Action from my items_controller.rb file:
def create
#list = List.find(params[:list_id])
#item = #list.items.create!(params[:item])
respond_to do |format|
format.html
format.js
end
end
This is my create.js file:
$('#item-container').prepend('<%= j render(partial: 'piece', locals: {item: #item}) %>');
This is my _piece.html.erb file:
<li><%= item.name %></l1>
This is my _single.html.erb file:
<div id="filter">
<div id="filter-left">
</div>
<div id="filter-right">
<%= link_to 'Delete', #list, :method => :delete %>
</div>
</div>
<div id="quick-add">
<%= form_for [#list, #item], :id => "form-quick", remote: true do |form| %>
<%= form.text_field :name, :id => "input-quick", :autocomplete => "off" %>
<% end %>
</div>
<ul class="item-container">
<% #list.items.incomplete.each do |item| %>
<% if item.id %>
<li><%= link_to "", complete_item_path(#list.id,item.id), :class => "button-item button-item-incomplete" %> <%= item.name %></li>
<% end %>
<% end %>
</ul>
<div class="title">Completed items</div>
<ul class="item-container">
<% #list.items.completed.each do |item| %>
<% if item.id %>
<li><div class="button-item button-item-completed"></div><%= item.name %></li>
<% end %>
<% end %>
</ul>
This is my home.html.erb file:
<div id="main-left">
<div id="main-left-1">
<%= link_to 'Add List', new_list_path, class: "button", id: "new_link", remote: true %>
</div>
<ul id="lists" data-update-url="<%= sort_lists_url %>">
<% #lists.each do |list| %>
<%= content_tag_for :li, list do %>
<%= link_to list.name, list, :remote => true, :class => "link" %>
<% end %>
<% end %>
</ul>
</div>
<div id="main-right">
</div>
Well, I had "item-container" as an ID instead of a class in the JS.ERB file. SILLY ERRORS!
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}"?