Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Explained on README how to deal with multi level nested fields.

  • Loading branch information...
commit ab9cd244eed31d81b85a3fc56079e93abe777fdf 1 parent 2cd97f3
@julianalucena authored
Showing with 88 additions and 14 deletions.
  1. +88 −14 README.md
View
102 README.md
@@ -57,23 +57,23 @@ The next step is set up the form view with the `nested_fields_for` method. It re
<%= form_for(@person) do |f| %>
<% # person fields... %>
-
+
<h2>Phones</h2>
<div class="container">
<%= f.nested_fields_for :phones do |f| %>
<fieldset class="item">
<%= f.label :number %>
<%= f.text_field :number %>
-
+
<a href="#" class="remove">remove</a>
-
+
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy %>
</fieldset>
<% end %>
</div>
<a href="#" class="add">add phone</a>
-
+
<% # more person fields... %>
<% end %>
@@ -119,7 +119,7 @@ And yeah, you need to mark it with the class `empty` or any other selector confi
When `nested_fields_for` is called, it also includes a `<script>` tag with the html template of a new item, so the javascript code knows what to insert. But sometimes it is not possible to put the template just after the items. For example, you can be inside a table (tables cannot have script elements inside it) or have multi-level nested items (the templates would be recursively repeated). In these cases you need to render the template manually.
To do this, just set the `render_template` option to `false` and use the `nested_fields_template` helper to put the templates anywhere on the page.
-
+
<%= f.nested_fields_for :phones, render_template: false do |f| %>
<% nested field code %>
<% end %>
@@ -146,7 +146,7 @@ For example, if you are using nested fields inside a table, you can do:
containerSelector: 'tbody',
itemSelector: 'tr'
});
-
+
#### Callbacks
@@ -161,9 +161,9 @@ Actions can be executed before or after items get inserted or removed. There are
console.log(item + ' was removed.');
}
});
-
+
The before callbacks also allow you to control when the element will be inserted or removed, so you can perform async operations (ajax, of course!) or choose to not insert or remove the element at all if some condition is not met. Just receive a second parameter as the handler function.
-
+
element.nestedFields({
beforeInsert: function(item, insert) {
$.get('/ajax_function', function() {
@@ -180,7 +180,7 @@ It is possible to control nested fields programmatically using a jQuery-style AP
element.nestedFields('insert', function(item) {
// Make some operation with item
}, {skipBefore: true});
-
+
The code above inserts a new item and does not execute the `beforeInsert` callback function. The complete list of available methods is shown below.
* `insert(callback, options)` inserts a new item in the container. The `callback` function is executed just before the item is inserted. There are two available options: `skipBefore` and `skipAfter`. Both arguments are optional.
@@ -207,7 +207,7 @@ It is easy to have multiple nested fields on the same page. Instead of applying
</div>
<a href="#" class="add">add phone</a>
</div>
-
+
<h2>Addresses</h2>
<div id="addresses">
<div class="container">
@@ -217,17 +217,92 @@ It is easy to have multiple nested fields on the same page. Instead of applying
</div>
<a href="#" class="add">add address</a>
</div>
-
+
// JS Code
$('#phones, #addresses').nestedFields();
+Multi Level Nested Fields
+-------------------------
+
+It is possible to have multi level nested items. To do this, you will need to use some other options when calling `nested_fields_for` and `nestedFields()`, so awesome nested fields can identify which item is dealing.
+
+### When calling `nested_fields_for`
+
+You will need to use the view option `new_item_index`, so the diferent form items can be identified.
+
+ <!-- ERB Code -->
+ <%= f.nested_fields_for :resources, new_item_index: 'new_resource_item' do |f| %>
+ <% ... %>
+ <% end %>
+
+Besides, the template of outsider field (that has another field inside) has to be rendered manually to avoid templates recursively repeated.
+
+ <!-- ERB Code -->
+ <div class="tasks-container">
+ <%= f.nested_fields_for :tasks, render_template: false, new_item_index: 'new_task_item' do |f| %>
+ <% ... %>
+ <% end %>
+ </div>
+ <%= nested_fields_templates %>
+
+The code above generates all templates with respective `new_item_index` like below:
+
+ <input id="project_tasks_attributes_new_task_item_resources_attributes_new_resource_item_name" name="project[tasks_attributes][new_task_item][resources_attributes][new_resource_item][name]" size="30" type="text"/>
+
+### When calling `nestedFields()`
+
+It is necessary to call `nestedFields()` in each level of fields, so you need to differentiate the elements (items, container, add, remove) of each model. It is also necessary to identify which template should be used by `itemTemplateSelector` option.
+Additionally when a first level nested field is added you have to use `afterInsert` callback to:
+
+1. Apply `nestedFields()` to it's nested field (so this deeper field can take advantage of awesome nested fields).
+
+2. Insert an item of the deeper model, so the user can gracefully fill it.
+
+
+CoffeeScript Code:
+
+ jQuery ($) ->
+ # Options for deeper nested fields
+ resourcesOptions = {
+ itemSelector: ".resource",
+ containerSelector: ".resources-container",
+ addSelector: ".resource-add",
+ removeSelector: ".resource-remove",
+ itemTemplateSelector: ".resource.template", # Identifies which template to use
+ new_item_index: "new_resource_index" # Same used on view options
+ }
+
+ # Apply nestedFields to the outsider nested fields (first nested fields level)
+ $(".project-form").nestedFields({
+ itemSelector: ".task",
+ containerSelector: ".tasks-container",
+ addSelector: ".task-add",
+ removeSelector: ".task-remove",
+ itemTemplateSelector: ".task.template",
+ new_item_index: "new_task_index",
+ afterInsert: (item) ->
+ # Applies nestedFields to this task's resources (deeper field)
+ item.find(".nested-level-2").nestedFields(resourcesOptions)
+ # Inserts a resource item (of the deeper field)
+ item.find(".nested-level-2").nestedFields("insert")
+ })
+
+ # Applies nestedFields to all projects tasks on page (to the second nested fields level)
+ $(".project-form").find(".nested-level-2").nestedFields(resourcesOptions)
+
+You can view a demo of multi level nested fields at https://github.com/julianalucena/multi_level_awesome_nested_fields_demo.
+
+
Demo
----
-There is a live demo at http://phonebook.guava.com.br/.
+There is a live demo at http://phonebook.guava.com.br/.
+
You can find the demo code at https://github.com/lailsonbm/awesome_nested_fields_demo.
+You can find the demo code of **multi level** awesome nested fields at https://github.com/julianalucena/multi_level_awesome_nested_fields_demo.
+
Compatibility
-------------
@@ -242,9 +317,8 @@ TODO
* Make sure it can degrade gracefully
* Implement jQuery autoload
* Make `nested_fields_for` works without a block (looking for partials)
-* Document how to nest nested fields (yeah, you can do that) ;-)
Copyleft
--------
-Copyleft (c) 2011 Lailson Bandeira (http://lailsonbandeira.com/). See LICENSE for details.
+Copyleft (c) 2011 Lailson Bandeira (http://lailsonbandeira.com/). See LICENSE for details.
Please sign in to comment.
Something went wrong with that request. Please try again.