4

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
LearningRoR
  • 26,582
  • 22
  • 85
  • 150
  • The first line in the solution was to be replaced in `add_fields` function. To make the class selector work, you need to change the user_product_fields partial to assign class instead of id. You would also need to scope the `$(".product_token").data("pre")` as I have done in the answer. – rubish Aug 19 '11 at 19:56
  • how did you manage to use data-pre in the nested inputs? – carpamon Jan 23 '12 at 22:01
  • @negarnil For when editing/updating a model right? – LearningRoR Jan 23 '12 at 22:03
  • yes, when I go to edit, the nested attributes which uses tokeninput are empty. in the railscast ryan uses "data-pre" => @book.authors.map(&:attributes).to_json. I don't know how to get the nested object. – carpamon Jan 23 '12 at 22:10
  • @negarnil Check out my edit now and make sure you put it in the following order or it won't load it. – LearningRoR Jan 23 '12 at 22:47
  • thanks, you don't data-pre to your inputs? like <%= f.text_field :product_token, :id => 'product_token' %> – carpamon Jan 23 '12 at 23:50
  • @negarnil, I did but I just wanted to keep the code as readable as possible. Glad I could help, Good luck! – LearningRoR Jan 24 '12 at 01:36

1 Answers1

2

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.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
rubish
  • 10,887
  • 3
  • 43
  • 57
  • Than you for the input, also, would you know how to get the Tokeninput class selector to work? It's not working when i put the following you have for TokenInput. – LearningRoR Aug 19 '11 at 19:21
  • Can you update the question with your current changes? I can't understand what is not working. – rubish Aug 19 '11 at 19:41
  • @rubish,wrbg -may I ask u to have a visit at http://stackoverflow.com/questions/9141176/facebook-style-jquery-tokeninput-script-retains-value-in-the-jquery-ui-modal-win ? just expecting u to contribute there in a question about tokeninput. n i donno whether such a request is acceptable in SOF – Istiaque Ahmed Feb 05 '12 at 06:14