Skip to content

Commit

Permalink
Merge pull request #49 from GimliLongBow/readme-update
Browse files Browse the repository at this point in the history
README update.
  • Loading branch information
ncri committed Oct 20, 2015
2 parents 60fa01c + 6f025a6 commit d9e9729
Showing 1 changed file with 99 additions and 72 deletions.
171 changes: 99 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ This Rails gem helps creating forms for models with nested has_many associations
It uses jQuery to dynamically add and remove nested associations.

- Works for arbitrarily deeply nested associations (tested up to 4 levels).
- Works with form builders like simple_form.
- Requires Ruby 1.9 and the Rails asset pipeline
- Works with form builders like [simple_form](https://github.com/plataformatec/simple_form).
- Requires Ruby 1.9+ and the Rails asset pipeline.



Expand All @@ -28,53 +28,63 @@ In your application.js file add:

Assume you have a user model with nested videos:

class User < ActiveRecord::Base
has_many :videos
accepts_nested_attributes_for :videos, allow_destroy: true
end
```ruby
class User < ActiveRecord::Base
has_many :videos
accepts_nested_attributes_for :videos, allow_destroy: true
end
```

Use the *nested_fields_for* helper inside your user form to add the video fields:
Use the `nested_fields_for` helper inside your user form to add the video fields:

= form_for @user do |f|
= f.nested_fields_for :videos do |ff|
= ff.text_field :video_title
..
```haml
= form_for @user do |f|
= f.nested_fields_for :videos do |ff|
= ff.text_field :video_title
..
```

Links to add and remove fields can be added using the *add_nested_fields_link* and *remove_nested_fields_link* helpers:
Links to add and remove fields can be added using the `add_nested_fields_link` and `remove_nested_fields_link` helpers:

= form_for @user do |f|
= f.nested_fields_for :videos do |ff|
= ff.remove_nested_fields_link
= ff.text_field :video_title
..
= f.add_nested_fields_link :videos
```haml
= form_for @user do |f|
= f.nested_fields_for :videos do |ff|
= ff.remove_nested_fields_link
= ff.text_field :video_title
..
= f.add_nested_fields_link :videos
```

Note that *remove_nested_fields_link* needs to be called within the *nested_fields_for* call and *add_nested_fields_link* outside of it via the parent builder.
Note that `remove_nested_fields_link` needs to be called within the `nested_fields_for` call and `add_nested_fields_link` outside of it via the parent builder.

## Link Customization

You can change the link text of *remove_nested_fields_link* and *add_nested_fields_link* like this:
You can change the link text of `remove_nested_fields_link` and `add_nested_fields_link` like this:

...
ff.remove_nested_fields_link 'Remove me'
...
f.add_nested_fields_link :videos, 'Add another funtastic video'
```haml
...
ff.remove_nested_fields_link 'Remove me'
...
f.add_nested_fields_link :videos, 'Add another funtastic video'
```

You can add classes/attributes to the *remove_nested_fields_link* and *add_nested_fields_link* like this:
You can add classes/attributes to the `remove_nested_fields_link` and `add_nested_fields_link` like this:

```haml
...
ff.remove_nested_fields_link 'Remove me', class: 'btn btn-danger', role: 'button'
...
f.add_nested_fields_link :videos, 'Add another funtastic video', class: 'btn btn-primary', role: 'button'
```

...
ff.remove_nested_fields_link 'Remove me', class: 'btn btn-danger', role: 'button'
...
f.add_nested_fields_link :videos, 'Add another funtastic video', class: 'btn btn-primary', role: 'button'

You can supply a block to the `remove_nested_fields_link` and the `add_nested_fields_link` helpers, as you can with `link_to`:

```haml
= ff.remove_nested_fields_link
Remove me %span.icon-trash
```

You can add a `data-confirm` attribute to the `remove_nested_fields_link` if you want the user to confirm whenever they remove a nested field:
You can add a `data-confirm` attribute to the `remove_nested_fields_link` if you want the user to confirm whenever they remove a nested field:

```haml
= ff.remove_nested_fields_link 'Remove me', data: { confirm: 'Are you sure?' }
Expand All @@ -84,71 +94,88 @@ You can add a `data-confirm` attribute to the `remove_nested_fields_link` if you

You can specify a custom container to add nested forms into, by supplying an id via the `data-insert-into` attribute of the `add_nested_fields_link`:

f.add_nested_fields_link :videos, 'Add another funtastic video', data: { insert_into: '<container_id>' }
```haml
f.add_nested_fields_link :videos, 'Add another funtastic video', data: { insert_into: '<container_id>' }
```

## Custom Fields Wrapper

You can change the type of the element wrapping the nested fields using the *wrapper_tag* option:
You can change the type of the element wrapping the nested fields using the `wrapper_tag` option:

= f.nested_fields_for :videos, wrapper_tag: :div do |ff|
```haml
= f.nested_fields_for :videos, wrapper_tag: :div do |ff|
```

The default wrapper element is a fieldset. To add legend element to the fieldset use:

= f.nested_fields_for :videos, legend: "Video" do |ff|
```haml
= f.nested_fields_for :videos, legend: "Video" do |ff|
```

You can pass options like you would to the `content_tag` method by nesting them in a `:wrapper_options` hash:

= f.nested_fields_for :videos, wrapper_options: { class: 'row' } do |ff|
```haml
= f.nested_fields_for :videos, wrapper_options: { class: 'row' } do |ff|
```

## Rails 4 Parameter Whitelisting

If you are using Rails 4 remember to add << NESTED_MODEL >>_attributes and the attributes to the permitted params.
Also, if you want to destroy the nested model you should add :_destroy and :id.
If you are using Rails 4 remember to add {{ NESTED_MODEL }}_attributes and the attributes to the permitted params.
If you want to destroy the nested model you should add `:_destroy` and `:id`.
For example:

# app/views/users/_form.haml.erb
= form_for @user do |f|
= f.nested_fields_for :videos do |ff|
= ff.remove_nested_fields_link
= ff.text_field :video_title
..
= f.add_nested_fields_link :videos
# app/controllers/users_controller
```haml
# app/views/users/_form.haml.erb
= form_for @user do |f|
= f.nested_fields_for :videos do |ff|
= ff.remove_nested_fields_link
= ff.text_field :video_title
..
def user_params
params.require(:user)
.permit(:name,:email,videos_attributes:[:video_title,:_destroy,:id])
# ^^^ ^^^ ^^^
# nested model attrs
# they will let you delete the nested model
end
= f.add_nested_fields_link :videos
```

```ruby
# app/controllers/users_controller
..
def user_params
params.require(:user)
.permit(:name,:email,videos_attributes:[:video_title,:_destroy,:id])
# ^^^ ^^^ ^^^
# nested model attrs
# they will let you delete the nested model
end
```

## Events

There are 4 javascipt events firing before and after addition/removal of the fields in the *nested_form_fields* namespace. Namely:
fields_adding, fields_added, fields_removing, fields_removed.
There are four JavaScript events firing before and after addition/removal of the fields in the `nested_form_fields` namespace:

- `fields_adding`
- `fields_added`
- `fields_removing`
- `fields_removed`

The events `fields_added` and `fields_removed` are triggered on the element being added or removed. The events bubble up so you can listen for them on any parent element.
This makes it easy to add listeners when you have multiple nested_form_fields on the same page.
This makes it easy to add listeners when you have multiple `nested_form_fields` on the same page.

CoffeeScript samples:

# Listen on an element
initializeSortable -> ($el)
$el.sortable(...)
$el.on 'fields_added.nested_form_fields', (event, param) ->
console.log event.target # The added field
console.log $(this) # $el

# Listen on document
$(document).on "fields_added.nested_form_fields", (event, param) ->
switch param.object_class
when "video"
console.log "Video object added"
else
console.log "INFO: Fields were successfully added, callback not handled."

```coffeescript
# Listen on an element
initializeSortable -> ($el)
$el.sortable(...)
$el.on 'fields_added.nested_form_fields', (event, param) ->
console.log event.target # The added field
console.log $(this) # $el

# Listen on document
$(document).on "fields_added.nested_form_fields", (event, param) ->
switch param.object_class
when "video"
console.log "Video object added"
else
console.log "INFO: Fields were successfully added, callback not handled."
```

## Contributing

Expand Down

0 comments on commit d9e9729

Please sign in to comment.