I'm attempting to create a "Save Changes" button for a form that would send data via ajax to the update method in the controller. The aim is to allow form users to save their work without the form reloading or redirecting. However I'm running into a bit of a problem; I'm getting the following error
undefined method `update_incorporation_path'
To be clear, incorporation is the controller that we're working with. Below is the code I added to accomplish this.
To my view, I added:
<%= button_to "", update_incorporation_path(#incorporation), :remote => true, :method => :post %>
To my routes, I added:
resources :incorporations do
member do
post 'update'
end
end
The update method looks like this:
def update
if #incorporation.update(incorporation_params)
if admin_signed_in?
#incorporations = Incorporation.all.order("created_at DESC")
else
#incorporations = current_user.incorporations("created_at DESC")
end
render action: "index"
else
render 'edit'
end
end
The complete view is below:
edit.html.erb
<%= render 'form' %>
<br/>
<%= link_to "Back", root_path, class: "btn btn-default" %>
_form.html.erb (the buttons are at the bottom)
<div id="wrapper" class="active main-content">
<%= simple_form_for #incorporation do |f| %>
<!-- Sidebar -->
<!-- Sidebar -->
<div id="sidebar-wrapper">
<ul id="sidebar_menu" class="sidebar-nav">
<li class="sidebar-brand"><a id="menu-toggle" href="#">Menu<span id="main_icon" class="glyphicon glyphicon-align-justify"></span></a></li>
</ul>
<% #sections=[["basic_info", "Basic Info"],["address", "Address"],["equity", "Equity"],["officers","Officers"],["directors", "Directors"],["contractor","Contractors"],["ip","IP"],["shareholders", "Shareholders"]] %>
<ul class="sidebar-nav" id="sidebar">
<% #sections.each do |section| %>
<li><span class="sub_icon glyphicon glyphicon-link"></span><%= section[1] %></li>
<% end %>
</ul>
<div id="save">Save</div>
</div>
<div class="panel-body">
<div id="basic_info" class="form_section">
<div class="form-left"><h2>Basic Info</h2></div>
<div class="form-right">
<%= f.simple_fields_for :company do |company| %>
<div class="padded-fields">
<%= render 'basic_fields', company:company %>
</div>
<% end =%>
<div class="padded-fields">
<div class="form_subsection">
<%= f.input :trademark_search, as: :radio_buttons, label: 'Would you like us to do a trademark search and provide advice regarding any issues we identify in relation to the name you have selected?', input_html: { class: 'form-control' } %>
</div>
</div>
</div>
</div>
<%= f.simple_fields_for :company do |company| %>
<div id="address" class="form_section">
<%= render 'address_fields' , company:company %>
</div>
<div id="equity" class="form_section">
<%= render 'equity_fields' , company:company %>
</div>
<div id="officers" class="form_section">
<div class="form-left"><h2>Officers</h2><br/><p>Please list the officers of the company.</p></div>
<div class="form-right">
<div>
<%= company.simple_fields_for :officers do |officer|%>
<%= render 'officer_fields', f: officer %>
<% end =%>
<%= link_to_add_association 'Add Officer', company, :officers, class: "btn btn-default add-button" %>
</div>
</div>
</div>
<div id="directors" class="form_section">
<div class="form-left"><h2>Directors</h2><br/><p>Please list the initial directors of the company. We recommend an odd number to avoid a deadlocked board.</p></div>
<div class="form-right">
<div>
<%= company.simple_fields_for :people do |person|%>
<%= render 'person_fields', f: person %>
<% end =%>
<%= link_to_add_association 'Add Director', company, :people, class: "btn btn-default add-button" %>
</div>
</div>
</div>
<div id="contractor" class="form_section">
<div class="form-left"><h2>Employees Contractors</h2></br><p>Please list all employees, independent contractors and any other individual or entity who will be providing services to the company at the time of incorporation. Each of these persons should have written agreements with the company. Please check the box next to each name for whom you would like us to prepare agreements</p></div>
<div class="form-right">
<div>
<%= company.simple_fields_for :contractor_people do |contractor| %>
<%= render 'contractor_person_fields', f:contractor %>
<% end =%>
<%= link_to_add_association 'Add Person', company, :contractor_people, class: "btn btn-default add-button" %>
</div>
<div class="form_subsection">
<div>
<%= company.simple_fields_for :contractor_orgs do |contractor| %>
<%= render 'contractor_org_fields', f:contractor %>
<% end =%>
<%= link_to_add_association 'Add Company', company, :contractor_orgs, class: "btn btn-default add-button" %>
</div>
</div>
</div>
</div>
<div id="ip" class="form_section">
<div class="form-left">
<h2>Intellectual Property</h2><br/><p>Please list existing intellectual property (including business plans, software, artwork, inventions, trade secrets and the like) that has been created for use in the company and the name of the person or people who created it.</p>
</div>
<div class="form-right">
<div>
<%= company.simple_fields_for :ips do |ip| %>
<%= render 'ip_fields', f: ip %>
<% end =%>
<div class="add-field"><%= link_to_add_association 'Add IP', company, :ips, class: "btn btn-default add-button" %></div>
</div>
</div>
</div>
<div id="shareholders" class="form_section">
<div class="form-left"><h2>Shareholders</h2><br/><p>Please list all individuals to hold equity in this company.</p></div>
<div class="form-right">
<div>
<%= company.simple_fields_for :shareholders do |shareholder|%>
<%= render 'shareholder_fields', f: shareholder %>
<% end =%>
<%= link_to_add_association 'Add Shareholder', company, :shareholders, class: "btn btn-default add-button" %>
</div>
</div>
</div>
<% end =%>
</div>
<%= f.button :submit, id:"incorporation_submit", class: "btn btn-primary" %>
<%= button_to "Update", incorporation_path(#incorporation), method: :post, remote: true %>
<% end =%>
</div>
I figure I must be forgetting something. Any thoughts are much appreciated.
Routes for update method was by default added when you wrote resources :incorporations, so change your routes to
resources :incorporations
And your path should be incorporation_path, also method in button_to is by default post, you don't need to write it,
change your button_to to
<%= button_to "Update", incorporation_path(#incorporation), :remote => true %>
But, if you are submitting a form, it should have a submit button instead of button_to, your form should look like this
<%= form_for #incorporation, remote: true do |f| %>
# form content
<%= f.submit "Submit" %>
<% end %>
Hope this helps!
Instead of :
<%= button_to "", update_incorporation_path(#incorporation),
:remote => true, :method => :post %>
Try :
<%= button_to "Update", incorporation_path(#incorporation),
method: :post, remote: true %>
In your route:
resources :incorporations
The resources ships with default actions index,new, create,edit, update, destroy. You don't need to declare it manually.
You can verify the routes from your console.
rake routes | grep 'incorporations'
You will get output like :
From here you can construct your path for the update action.
Hope it helps :)
Related
I currently have 3 separate views, two using AJAX to create/edit tasks.
I'm trying to set a date that the task is due, and would like to present some options to the user for today, one week from today, two weeks for today, all contained within one partial that I can use across all three forms.
I thought I'd do this using AJAX, and simply update that one area of the form to change the default value of the variable, however, I can't render the form.
If there is a better way of doing this instead please let me know.
I get the following error:
ActionView::Template::Error (undefined local variable or method `form' for #<#<Class:0x00007fe8a4ccd8e8>:0x00007fe8a4b64df8>
Did you mean? for
fork):
1: $("#date-container").html(" <%= j render partial: "goal_tasks/set_due_date", locals: { task: #goal_task, form: form } %>");
edit.html.erb (with extra fields snipped):
<%= render 'layouts/pagetitle', title: "Edit Task" %>
<%= form_for([#goal_task.goal, #goal_task]) do |form| %>
<div class="form-group col-md-10 col-md-offset-1">
<%= render 'layouts/errors', object: #goal_task %>
<div class="form-group col-md-12" id="date-container">
<%= render partial: "goal_tasks/set_due_date", locals: { task: #goal_task, form: form } %>
</div>
<div class="form-group col-md-12">
<%= form.submit class:"btn btn-success", value: "Edit Task" %>
</div>
</div>
<% end %>
routes:
resources :goals do
resources :goal_tasks do
member do
get :set_task_due_date
end
end
_set_due_date.html.erb:
<% if local_assigns[:date] %>
<%= form.hidden_field :taskduedate, value: date %>
<% elsif local_assigns[:due_date] %>
<div class="control-label col-sm-3">
<%= form.label :taskduedate, "Task due:" %>
</div>
<div class="col-sm-9 form-align-left">
<%= form.date_select(:taskduedate, selected: due_date) %>
</div>
<% elsif task.taskduedate.present? %>
<div class="control-label col-sm-3">
<%= form.label :taskduedate, "Task due:" %>
</div>
<div class="col-sm-9 form-align-left">
<%= form.date_select :taskduedate %>
</div>
<% else %>
<div class="control-label col-sm-3">
<%= form.label :taskduedate, "When is your task due? " %>
</div>
<div class="col-sm-9 form-align-left">
<%= form.date_select :taskduedate %>
</div>
<% end %>
<span class="p-4">
<%= link_to "Today", set_task_due_date_goal_goal_task_path(task.goal, task, :due_date => Date.today), remote: true %> |
<%= link_to "Next week", set_task_due_date_goal_goal_task_path(task.goal, task, :due_date => Date.today + 7.days), remote: true %> |
<%= link_to "Two weeks", set_task_due_date_goal_goal_task_path(task.goal, task, :due_date => Date.today + 14.days), remote: true %>
</span>
set_task_due_date.js.erb:
$("#date-container").html(" <%= j render partial: "goal_tasks/set_due_date", locals: { task: #goal_task, form: form } %>");
controller:
def set_task_due_date
due_date = params[:due_date]
respond_to do |format|
format.js
end
end
The solution, thanks to Muhammad Abdullah Khalil via a Rails slack channel is that I had to declare the form inside of the partial.
I created a form on my application that is suposed to delete some media on my app.
I have a Album entity that has some media on it. I created a partial called media_uploader so I can reuse it on other places. Im calling my partial from the albums/new view. Like this:
<%= render '/profiles/edit/sidebar', user: current_user %>
<article class="col-9 col-offset-1">
<h3 class="color-gray-medium">Album Info</h3>
<div class="row row-no-padding top-5">
<%= form_for #album do |f| %>
<div class="col-9">
<div class="form-group row" >
<div class="col-6">
<label for="">Name:</label>
<%= f.text_field :name %>
</div>
</div>
</div>
<div class="col-9">
<div class="form-group row" >
<div class="col-6">
<%= render 'shared/media_uploader', media_contents: #media_contents %>
</div>
</div>
</div>
shared/_media_uploader.html.erb
<%= link_to 'Delete', delete_media_path, method: :delete, id: 'delete-all', class: 'btn btn-danger', disabled: media_contents.empty? %>
<br><br>
<div class="row">
<div id="media-contents" class="col-12">
<% if media_contents.empty? %>
<h5 id="no-media">No Media Found</h5>
<% else %>
<% media_contents.each do |media| %>
<div class="col-4">
<div class="thumbnail">
<%= image_tag media.file_name_url(:thumb) %>
<div class="caption">
<p>
<%= check_box_tag 'media_contents[]', media.id %>
</p>
</div>
</div>
</div>
<% end %>
</div>
</div>
<% end %>
<% end %>
My routes are like this:
resources :media_contents, only: [:create]
delete 'delete_media', to: "media_contents#delete_media"
delete 'delete_all', to: 'media_contents#delete_all'
When I click on the delete button here:
<%= form_tag({controller: "media_contents", action: "delete_media"}, method: "delete") do %>
<%= submit_tag 'Delete', id: 'delete', class: 'btn btn-danger', disabled: media_contents.empty? %>
It gives a error:
No route matches [DELETE] "/albums"
I understand that this is caused because of the outside form_for: #album.
The question is: "How can I do this?" How can I, inside this #album form, call a method from another controller and make it works?
Looks like you routes of media_contents is limited to "create"
Adding :delete could solve the issue
resources :media_contents, only: [:create, :delete]
Also why add a custom routes for delete when DELETE action already exists for the controller?
I could be that your form_tag of media_contents is inside the form_tag of albums.
That could be one of the reasons it's calling "albums" controller
You can't use form inside another form, it is invalid html. But you can use 2 submit buttons and decide what to do inside the controller action, depending on commit parameter. You need to remove inner form_tag from the partial and change update action like:
if params[:commit] == "Delete"
# deletion logic or redirect to needed delete action goes here
else
# existing `update` goes here
end
I have a form like that:
<%= form_for #report do |f| %>
<div class="row">
<div class="col-sm-9">
<h3 class="page-header">
Children
</h3>
<div class="row">
<% students.each do |student| %>
<div class="col-xs-4 col-md-2">
<div class="std_container">
<%= check_box_tag "student_ids[]", student.id, nil, {id: "check_#{student.id}", class: "student_check"} %>
<%= label_tag "check_#{student.id}" do %>
<div class="std_label"><%= student.name %></div>
<div class="std_img thumbnail"><img src="http://www.codeproject.com/KB/GDI-plus/ImageProcessing2/img.jpg" alt=""></div>
<% end %>
</div>
</div>
<% end %>
</div>
</div>
<%= render "form_categories", f: f, report_notes: #report.report_notes %>
<%= render "messages/form", ????? %>
</div>
</div>
</div>
<% end %>
And I need to render these two partials on the bottom. The 'messages' partial is a form that responds to a different controller but needs to use the "student_ids[]" parameter present on the #report form together with its own parameters. This partial is:
<%= form_for #message do |f| %>
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<%= f.hidden_field :professor_id, :value => current_user.professor.id %>
<%= f.label :text, "Texto" %>
<%= f.text_area :text %>
<%= f.submit "Enviar", class: "btn btn-default" %>
</div>
</div>
<% end %>
How do build this "messages" partial in a way that I can use the "student_ids[]" and submit it to its controller?
It is not possible. I solved this problem by using javascript.
I am trying to do simple quiz using Rails and Bootstrap, but I have problem with checkboxes being too wide on small screens and it covers label of that checkbox (.
My view looks like this:
<div class="center jumbotron">
<h2><%= t(:quiz) %></h2>
<div>
<%= form_for(:test, url: quiz_path) do |f| %>
<% #quiz.tasks.each_with_index do |task, index| %>
<div>
<% if task = Task.find_by(id: task) %>
<%= image_tag(task.asset, class: "img-responsive") %>
<%= task.text %>
<% answers = task.correct_answers + task.wrong_answers %>
<% answers.shuffle! %>
<fieldset>
<!-- Dodać półotwarte -->
<% answers.each do |answer| %>
<div class="checkbox">
<%= f.check_box("task#{index}", {class: "checkbox", multiple: true}, answer, nil)%>
<%= f.label "task#{index}", answer %>
</div>
<% end %>
</fieldset>
<% end %>
</div>
<% end %>
<%= f.submit t(:finish_quiz), class: "btn btn-lg btn-primary" %>
<% end %>
</div>
</div>
How do I make it look normal a.k.a. like desktop version, just bigger (square-like of course)?
I have a form that posts something to a feed. I would like an user to post to the feed if they are signed in, but if they are not and they hit submit, I would like them to see the login modal. Here is my current form without this logic. It's a basic form_for - nothing special.
<%= form_for(#sub_opp) do |f| %>
<div class="field">
<%= f.label :sport, :class=>'form_label' %>
<%= f.select :sport, ['Basketball', 'Beach Volleyball', 'Flag Football'] %>
</div>
<div class="field" id = "datetime_select">
<%= f.label :Sub_Date, :class=>'form_label' %>
<%= f.datetime_select :sub_time, :ampm => true, :minute_step => 15 %>
</div>
<div class="actions">
<%= f.submit 'POST', :class=>"btn btn-success btn-large" %>
</div>
<% end %>
Conceptually, I would like to incorporate logic in along these lines when one clicks the submit button.
<% if current_user.present? %>
Submit the form
Otherwise
<a href="#myModal" data-toggle="modal">
Can you do this with a form_for? Thanks
I figured it out with a simple if / then statement. Surprised i did not think of this earlier. Thanks.
<% if current_user.present? %>
<div class="field">
<%= f.hidden_field :poster_user_id, :value => current_user.id %>
</div>
<div class="actions">
<%= f.submit 'POST', :class=>"btn btn-success btn-large" %>
</div>
<%else%>
<div class="actions">
POST
</div>
<%end%>