I am using the setup of the R.B. railcast - #197 Nested Model Form Part 2 to dynamically add fields to the form but i am having issues getting the Tokeninput fields to work.
Form:
<%= 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 %>
This is my user_product_fields partial, the token text_fields are what I'm having the issue with:
<div class="fields">
<%= f.label :product_token, "Product" %>
<%= f.text_field :product_token, :id => 'product_token' %>
<%= f.label :address_token, "Address" %>
<%= f.text_field :address_token, :id => 'address_token' %>
<%= f.label :price %>
<%= f.text_field :price %>
<%= link_to_remove_fields "remove", f %>
</div>
Jquery Tokeninput functions inside of my application.js:
$(function() {
$("#product_token").tokenInput("/products.json", {
prePopulate: $("#product_token").data("pre"),
tokenLimit: 1
});
});
$(function() {
$("#address_token").tokenInput("/business_addresses.json", {
prePopulate: $("#address_token").data("pre"),
tokenLimit: 1
});
});
What the nested form does in the function is this:
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));
}
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}
This line here:
var new_id = new Date().getTime();
Makes the tokeninput fields dynamic, this is what i pulled up from the HTML, notice the changing long numbers in the fields. This is because of the line above.
<label for="user_user_products_attributes_1313593151076_product_token">Product</label>
<label for="user_user_products_attributes_1313593146876_product_token">Product</label>
<label for="user_user_products_attributes_1313593146180_product_token">Product</label>
How can i get my token fields to work when the fields keep changing up?
Thank you.
EDIT: New working code.
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(content.replace(regexp, new_id)).insertBefore($(link).parent()).trigger("nestedForm:added");
}
$('div.fields').live("nestedForm:added", function() {
$("#product_token", $(this)).tokenInput("/products.json", {
prePopulate: $("#product_token", $(this)).data("pre"),
tokenLimit: 1
});
});
When trying to data-pre
with TokenInput:
def new
@user_product = current_user.user_products.build
# This line below is for TokenInput to work, This allowed me to use @products.map on the form.
@products = []
end
def edit
@user_product = UserProduct.find(params[:id])
# This line below had to find the Product associated with the UserProduct
@products = [@user_product.product]
end
You can user jQuery's insertBefore instead of before as that will return the inserted element. It will help you to trigger some event. You can have a listener on this event, in which you can have you token-input code. You should also use class instead of id, as many elements can have same class, but no two elements should have same id.
$(content.replace(regexp, new_id)).insertBefore($(link).parent()).trigger("nestedForm:added");
$('div.fields').live("nestedForm:added", function() {
$(".product_token", $(this)).tokenInput("/products.json", {
prePopulate: $(".product_token", $(this)).data("pre"),
tokenLimit: 1
});
});
This is just an idea, code is not tested.