Skip to content
This repository has been archived by the owner on Dec 12, 2021. It is now read-only.

How To: Add fields with pre defined values

H. Can Yıldırım edited this page Feb 18, 2017 · 3 revisions

Note: This example uses jQuery, but you could easily use the same concept to write it Prototype

Sometimes you may want to add a set of fields with one or more pre-defined values. For this example, let's say you are creating an application where users can add multiple credit cards. Normally you would have an 'Add Credit Card' button, which would simply add blank fields. But say you want to have buttons to add each of the major credit cards with the name pre-defined (e.g. an 'Add Visa' button).

First, since this is a little bit more than a simple change, you will need to have a local copy of jquery_nested_form.js, which you can get here jquery_nested_form.js. Place this in your app/assets/javascripts folder and it will override the one being pulled in from the gem.

Next, we need to modify the addFields function. Within the addFields function, look for the following block of code:

      ...
      field
        .trigger({ type: 'nested:fieldAdded', field: field })
        .trigger({ type: 'nested:fieldAdded:' + assoc, field: field });
      ...

Then change that block of code to:

      ...
      field
        .trigger({ type: 'nested:fieldAdded', field: field, link: link })
        .trigger({ type: 'nested:fieldAdded:' + assoc, field: field, link: link });
      ...

What we are doing here is passing another variable (the link variable, which is the link that was clicked) to the nested:fieldAdded events. Now we will be able to access the link when listening for the nested:fieldAdded events.

Next, we are going to make a few minor modifications to your nested form code in your view:

  <%= f.fields_for :credit_cards do |credit_card_form| %>
    <div>
      <%= credit_card_form.input :name, :class => 'name' %>
      <%= credit_card_form.link_to_remove 'Remove', :confirm => 'Are you sure you want to remove this credit card?' %>
    </div>
  <% end %>
  <div class='add_links'>
    <%= f.link_to_add 'Visa', :credit_cards, :'data-predefined-name' => 'Visa' %>
    <%= f.link_to_add 'Discover', :credit_cards, :'data-predefined-name' => 'Discover' %>
  </div>

The two items to note here are:

  • We added a class to the name input, called name (this will be used to find the field)
  • We added a 'data-predefined-name' to each link_to_add (this is the value we want to use to populate the field)

Last we are going to write a little bit of Javascript to handle this:

$("#paycheck_planner_form").on("nested:fieldAdded", function(event) {
  var name_field;
  name_field = event.field.find('.name');
  return name_field.val($(event.link).data('predefined-name'));
});

or

$ ->
  $('#paycheck_planner_form').on 'nested:fieldAdded', (event) ->
    name_field = event.field.find('.name')
    name_field.val $(event.link).data('predefined-name')

This code is listening for nested:fieldAdded, you could also listen for nested:fieldAdded:model (where model is the name of your model, in our case it would be nested:fieldAdded:credit_cards, useful if you have multiple nested forms on the page and want to have different functionality). This code is finding the field by the class we added to our view (.name), and setting the value of that field to the 'data-predefined-name' we set for each link_to_add in the view. If you still want to add a blank field, simply don't define the 'data-predefined-name' the link_to_add.

This is a very basic example, only setting one pre-defined field. If needed, you could modify the code to pre-define as many fields as needed.