Im trying to append a form_for to a div with no luck, I've been through everything in the javascript console inside the div that holds the form but can't seem to find the contents to target. Please let me know if this is hard to understand and i'll try to explain myself better. I have also tried
$('.admin-right-content').innerHTML = "<%= render 'products/add_products' %>"
$(".admin-right-content").append("<%= escape_javascript(render(:partial => #add_products) %>");
$(".admin-right-content").append("<%= escape_javascript(render(:partial => add_products) %>");
$(".admin-right-content").append("<%= escape_javascript(render add_products %>");
$('.admin-right-content').append($('.add-products-form'))
The list goes on and on.
I'm a newbie to Rails, so apologies if this turns out to be something simple or some silly mistake on my end.
The partial containing the form is _add_products.html.erb.
Instead of printing the form out its actually appending the code to the div.
<div class="add-products-form">
<%= form_for #product do |form| %>
<%= form.label 'Product name' %>
<%= form.text_field :product_name %>
<%= form.label 'Type'%>
<%= form.text_field :type %>
<%= form.label 'Price' %>
<%= form.text_field :price %>
<%= form.label 'Description' %>
<%= form.text_area :description %>
<%= form.label 'Add photos' %>
<%= form.data_field :photos %>
<%= form.submit "Submit" %>
<% end %>
</div>
You can try this:
$('.admin-right-content').append($('.add-products-form').children().clone())
I'm completing a project. I have a search field that accepts a url. Upon submit, my code scrapes data from a website and saves it in a variable. I want to use that data to automatically fill in form fields for the user on that same page.
Here's what I currently have in the view:
<%= provide(:title, "New Deal") %>
<h3 class="create">Step 1: <span class="text">Enter the wholesale URL and click add button to create a new deal.</span></h3>
<%= form_tag new_deal_path, id: "search-form", method: :get do %>
<p>
<%= label_tag(:search, "Enter the URL:") %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Add Deal", name: nil, class: "scrape-trigger", remote: true %>
</p>
<% end %>
<% end %>
Here's my controller action:
def new
if params[:search]
#response = Deal.search(params[:search])
respond_to do |format|
format.js
end #currently, can't get this to work.
end
#deal = Deal.new
#deal.orders.build
#user = User.new
end
And here is the form I want to fill:
<div class="manual-deal">
<%= f.label :url %><br>
<%= f.url_field :url %><br><br>
<%= f.label :title %><br>
<%= f.text_field :title %><br><br>
<%= f.label :image %><br>
<%= f.file_field :image %><br><br>
<%= f.label :retail_price_cents %><br>
<%= f.text_field :retail_price_cents %><br><br>
<%= f.label :wholesale_price_cents %><br>
<%= f.text_field :wholesale_price_cents %><br><br>
<%= f.label :minimum_bids %><br>
<%= f.number_field :minimum_bids %><br><br>
<%= f.label :estimated_delivery %><br>
<%= f.date_field :estimated_delivery %><br><br>
<%= f.label :delivery_method %><br>
<%= f.select :delivery_method, ['USPS', 'UPS', 'FedEX', 'Shyp', 'Local Pickup'] %><br><br>
<%= f.label :description %><br>
<%= f.text_area :description %><br>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
data-description="Charge"
data-amount="<%=#deal.wholesale_price_cents%>">
</script>
<% end %>
Following the advice on another question, I created a new.js.erb file in the view where I want this to happen. I thought I could fill the fields from there using:
function ready() {
$('.scrape-trigger').on("click", function() {
$('#deal_url').val(params[:search]);
$('#deal_title').val(title);
$('#deal_image').val(image);
$('#deal_wholesale_price_cents').val(price_range);
$('#deal_description').val(description);
});
};
$(document).on('ready page:load', ready)
Not quite sure about this last part. Can someone point me in the right direction? I've been stuck on this for hours and haven't found a decent solution. I've found some other resources on Ajax, but nothing that works with what I need with this scraped data.
Cheers.
I'm assuming #response has all the information you're going to need when filling out the form. (Also note that #deal and #user will not be available to new.js.erb because they are defined after you render that file.)
This .js.erb file is rendered exactly once, exactly when it is rendered. Because of that, you don't need to worry about any $(document).on('ready page:load', ready) nonsense. You don't want this code to run when the page has loaded, you want it to run when the file is rendered. Get rid of it!
You should be left with just the .val() lines. This is a fine way to go about setting the value of things, but this file has no idea what params[:search] or title is. The only variable you passed to this file is #response. Use it!
So you should end up with something like the following:
$('#deal_url').val(#reponse.url);
$('#deal_title').val(#reponse.title);
$('#deal_image').val(#reponse.image);
$('#deal_wholesale_price_cents').val(#reponse.price_range);
$('#deal_description').val(#reponse.description);
UPDATE
Thank you for your answer.
But If I remove
for requested_role in #project.requested_roles
from the partial, then I can't access to the requested_role.role value, because I don't have the parameter X obtained from the code
for X in #projects.requested_roles
and I can't write X.role
How can I access this value without using for or .each to scroll the requested_roles of the project?
END UPDATE
I've a problem with a social network I'm developing with Ruby on Rails. I followed the railscasts 196 and 197 to create a form with fields_for and to add fields dinamically with javascript, but I have 2 major problems.
A User can create a Project and this Project must have 1+ Requested_roles.
When I open the project edit page to change the roles, if there are N requested_roles for the project, I see N*N forms to change the requested_roles. So if I have 2 requested_roles (for example Director and Producer) I see 4 select fields, Director - Producer - Director -Producer. They are repeated N times. And I can't modify them because I can have max 1 requested_role of each type. It's fine if I have only 1 requested_role (because 1x1=1)
Project.rb
class Project < ActiveRecord::Base
attr_accessible :title, :requested_roles_attributes, :video, :num_followers, :num_likes
belongs_to :user
has_many :requested_roles, dependent: :destroy
accepts_nested_attributes_for :requested_roles, :reject_if => lambda { |a| a[:ruolo].blank? }, :allow_destroy => true
Requested_role.rb
class RequestedRole < ActiveRecord::Base
attr_accessible :role, :project_id
belongs_to :project
Projects_controller.rb
class ProjectsController < ApplicationController
def new
#project= Project.new
#requested_role= #project.requested_roles.build
end
Projects/edit.html.erb
<div class="row">
<div class="span6 offset3">
<%= form_for(#project) do |f| %>
<%= render 'shared/error_messages', object: f.object%>
<%= f.label :title, "Project title" %>
<%= f.text_field :title %>
<%= f.fields_for :requested_roles do |builder| %>
ciao
<%= render 'requested_role', :f => builder %>
<% end %>
<div class="fields">
<p><%= link_to_add_fields "Add requested role", f, :requested_roles %></p>
</div>
</br>
<%= f.submit 'Apply changes', class: 'btn btn-large btn-primary' %>
<% end %>
</div>
</div>
I think that the error is in this view (Projects/edit):
<%= f.fields_for :requested_roles do |builder| %>
ciao
<%= render 'requested_role', :f => builder %>
<% end %>
this code, even without the partial, lead to a N-times repeated requested_roles. In fact, without the partial _requested_role, we have N "ciao", but we should have only one.
projects/_requested_role.html.erb
<% if #project.requested_roles.any? %>
<p>Modifica ruoli richiesti </p>
<%end%>
<%= #project.requested_roles.count %>
<% for requested_role in #project.requested_roles %>
<div class="fields">
<p>
<p>Requested role: <%= role_to_string(requested_role.role) %></p>
<%= f.label :role, "Modify role" %>
<%= f.select :role, options_for_select([["Regista",1],["Sceneggiatore", 2],["Direttore della fotografia", 3], ["Operatore",4],
["Fonico", 5], ["Montatore", 6], ["Truccatrice",7], ["Costumista",8], ["VFX Artist",9],
["Produttore", 10], ["Attore",11], ["Attrice",12], ["Grip/Runner",13]], :selected => requested_role.role) %>
<%= link_to_remove_fields "remove", f %> #dinamically remove a field
</p>
<% end %>
</div>
Can you help me please? I can't figure out where the error is. Thank you in advance.
The other problem is related to the links to dinamically delete and add requested_roles (javascript-jquery).
If I have 3 requested_roles (9 select fields instead of 3 because of the error that I mentioned before) and I delete (through link_to_remove_fields) the last one there's no problem. But if I delete the first one, the fields and even the submit button below it disappear and I can't modify the roles or submit the changes.
When I add (through link_to_add_fields) a new role and I already have, for example, 2 requested_roles (Director, Producer), when I click on the link to add the new requested_role another bug occurres. Instead of a select field to choose the role, a copy of the 2 existing select fields (Director, Producer) appears.
application_helper.rb
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
end
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize, :f => builder)
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
end
Application.js
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
I can't understand what goes wrong. If you have some idea can you give me some advice? Thank you very much.
Dario
The problem is that you're iterating twice.
<%= f.fields_for :requested_roles do |builder| %>
ciao
<%= render 'requested_role', :f => builder %>
<% end %>
Will automatically repeat the requested_role partial for each requested role. That's why it shows "ciao" N times, because that's what fields_for does at render. You probably need to read the doc to understand how it works: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
So there is no need to have
for requested_role in #project.requested_roles
in your partial. It will only repeat all requested roles each time fields_for renders it. Here's what your code should look like in your edit.html.erb :
<% if #project.requested_roles.any? %>
<p>Modifica ruoli richiesti </p>
<%end%>
<%= #project.requested_roles.count %>
<%= f.fields_for :requested_roles do |builder| %>
<%= render 'requested_role', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add requested role", f, :requested_roles %></p>
And the requested_role partial should simply be:
<div class="fields">
<div>
<p>Requested role: <%= role_to_string(f.object.role) %></p>
<%= f.label :role, "Modify role" %>
<%= f.select :role, options_for_select([["Regista",1],["Sceneggiatore", 2],["Direttore della fotografia", 3], ["Operatore",4],
["Fonico", 5], ["Montatore", 6], ["Truccatrice",7], ["Costumista",8], ["VFX Artist",9],
["Produttore", 10], ["Attore",11], ["Attrice",12], ["Grip/Runner",13]], :selected => f.object.role) %>
<%= link_to_remove_fields "remove", f %>
</div>
</div>
Fixing your partial should fix your second problem with the links.
You might want to consider using Ryan's gem for nested_forms
https://github.com/ryanb/nested_form
I have the model Box, and each Box has many box_videos (another model). I want the user to be able to add box_videos to the box, so I created the following edit form for that (after creation of #box):
<%= form_tag "/box_videos", { method: :post, id: "new_box_videos", remote: true } do %>
<%= text_field_tag "box_videos[][link]", '' %>
<%= text_area_tag "box_videos[][description]", '' %>
<%= hidden_field_tag("box_videos[][box_id]", #box.id) %>
<%= hidden_field_tag("box_videos[][user_id]", current_user.id) %>
<div class="another_video">Add Another Video</div>
<%= submit_tag "Save Videos" %>
<% end %>
<%= form_for(#box) do |f| %>
<%= f.text_field :name %>
<%= f.text_field :size %>
<%= f.text_field :all_other_attributes %>
<%= f.submit "Create Box" %>
<% end %>
And some Javascript to facilitate adding more box_videos in one click.
<script>
$('.another_video').click(function() {
$('#new_box_videos').prepend('<input id="box_videos_link" name="box_videos[][link]" placeholder="Link to a youtube video." style="width: 18em;" type="text" value=""><textarea id="box_videos_description" name="box_videos[][description]" placeholder="Describe this video." style="width: 18em;"></textarea><br/><br/><input id="box_videos_box_id" name="box_videos[][box_id]" type="hidden" value="' + gon.box_id.toString() + '"><input id="box_videos_user_id" name="box_videos[][user_id]" type="hidden" value="' + gon.user_id.toString() + '">');
});
</script>
The above code works, in that params[:box_videos] when submitting three box_videos is as follows:
[{"link"=>"https://www.youtube.com/watch?feature=player_detailpage&v=dpAP8bq3ddU
", "description"=>"foo", "box_id"=>"63", "user_id"=>"16"}, {"link"=>"https
://www.youtube.com/watch?feature=player_detailpage&v=dpAP8bq3ddU", "description"
=>"bar", "box_id"=>"63", "user_id"=>"16"}, {"link"=>"https://www.you
tube.com/watch?feature=player_detailpage&v=dpAP8bq3ddU", "description"=>"hello world",
"box_id"=>"63", "user_id"=>"16"}]
In my controller I would just create a box_video object for every hash in the array and it works out just fine. BUT the problem comes when each time I submit the nested form_tag form, I send multiple requests to the controller action! Which means there are duplicates being created.
I can think of adding logic to the box_videos controller create action to check for duplicate content, but it seems rather hacky. Can anyone please let me know why this is happening?
You can't have nested form elements according to the html spec (see this answer).
You might want to use nested forms for this, it provides the creation of associated models via jquery with useful form_helper wrappers.
I have a form that has no nested models.
class UserProductsController
def new
#user_product = current_user.user_products.build
end
end
With jquery/javascript i want to add and remove new #user_product fields on the same form. This how it would look normally:
<%= form_for(#user_product) do |f| %>
<%= f.error_messages %>
<%= f.text_field :product %>
<%= f.text_field :address %>
<%= f.text_field :price %>
<%= f.submit %>
<% end %>
And I'm trying to achieve:
<%= form_for(#user_product) do |f| %>
<%= f.error_messages %>
<%= f.text_field :product_name %>
<%= f.text_field :address %>
<%= f.text_field :price %>
---New ID(New generated ID, could be any new number in the database)
<%= f.text_field :product_name %>
<%= f.text_field :address %>
<%= f.text_field :price %>
<%= Remove this Product %> # ajax style, this link removes this product entirely
----ID 3----
<%= f.text_field :product_name %>
<%= f.text_field :address %>
<%= f.text_field :price %>
<%= Remove this Product %>
-----Add link------
<%= Add Another Field %> # ajax style adding
<%= f.submit %>
<% end %>
Notice the new IDs that aren't preset and the one submit button so this way more then one Product can be created at a time by a User. How do i achieve the above?
Thank you.
Answer:
Using the User.rb model you can do what James said. Here is my form that works.
<%= form_for(current_user, :url => user_products_path) do |f| %>
<%= f.error_messages %>
<%= f.fields_for :user_products do |builder| %>
<%= render "user_product_fields", :f => builder %>
<% end %>
<%= link_to_add_fields "Add a UserProduct", f, :user_products %>
<%= f.submit "Create" %>
<% end %>
_user_product_fields.html.erb
<div class="fields">
<%= f.label :product, "Product" %>
<%= f.text_field :product %>
<%= f.label :address, "Address" %>
<%= f.text_field :address %>
<%= f.label :price %>
<%= f.text_field :price %>
<%= link_to_remove_fields "remove", f %>
</div>
As others have suggested (somewhat unhelpfully), use nested forms.
You need the form to be based on the current_user object with fields_for declaration for :user_products. You will need to set the url for the form to post back to the user_product controller not the user controller using url_for and you will need to adjust the user_product controllers update and create actions to make use of params[:user] instead of params[:user_product]
If you have your accepts_nested_attributes configured properly all should be good.
BTW if you follow those railscasts you will find that the javascript to add new will not work for Rails 3.x
You should use something like this for your view helpers
module ApplicationHelper
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
end
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to_function(name, "add_fields(this, '#{association}', '#{escape_javascript(fields)}')")
end
end
and something like this for your javascript in your application.js file
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
function remove_fields(link) {
$(link).previous("input[type=hidden]").value = "1";
$(link).up(".fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).up().insert({
after: content.replace(regexp, new_id)
});
}
and obviously your form_for need to be refactored to something like this
<%= form_for(current_user, :url => user_product_path) do |f| %>
<!-- add your f.fields_for :user_products here, probably in a rendered partial -->
<%end%>
That should be enough with the rails casts to get you going
Checkout this:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
You can use cocoon for this.