cocoon 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +8 -4
- data/Gemfile +7 -5
- data/Gemfile.lock +152 -0
- data/History.md +5 -0
- data/README.markdown +149 -168
- data/VERSION +1 -1
- data/cocoon.gemspec +28 -19
- data/gemfiles/Gemfile.rails-3.2.13 +21 -0
- data/gemfiles/Gemfile.rails-3.2.13.lock +154 -0
- data/lib/cocoon.rb +3 -1
- data/lib/cocoon/view_helpers.rb +4 -0
- data/spec/cocoon_spec.rb +174 -91
- data/spec/dummy/app/models/comment.rb +3 -1
- data/spec/dummy/app/models/post.rb +5 -1
- data/spec/dummy/config/environments/development.rb +1 -1
- data/spec/dummy/config/initializers/rails_version_helper.rb +6 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -6
- data/spec/support/rails_version_helper.rb +3 -0
- data/spec/support/shared_examples.rb +73 -0
- metadata +76 -54
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -2,15 +2,17 @@ source "http://rubygems.org"
|
|
2
2
|
|
3
3
|
|
4
4
|
group :development, :test do
|
5
|
-
gem "rails", ">=
|
6
|
-
gem "sqlite3
|
5
|
+
gem "rails", ">=4.0.0"
|
6
|
+
gem "sqlite3"
|
7
7
|
gem "json_pure"
|
8
8
|
gem "jeweler"
|
9
|
-
gem "rspec-rails", ">= 2.
|
10
|
-
gem "rspec", ">= 2.
|
11
|
-
gem "actionpack", ">=
|
9
|
+
gem "rspec-rails", ">= 2.8.0"
|
10
|
+
gem "rspec", ">= 2.8.0"
|
11
|
+
gem "actionpack", ">=4.0.0"
|
12
12
|
gem "simplecov", :require => false
|
13
13
|
|
14
|
+
gem 'nokogiri'
|
15
|
+
|
14
16
|
gem "generator_spec"
|
15
17
|
end
|
16
18
|
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
actionmailer (4.0.0)
|
5
|
+
actionpack (= 4.0.0)
|
6
|
+
mail (~> 2.5.3)
|
7
|
+
actionpack (4.0.0)
|
8
|
+
activesupport (= 4.0.0)
|
9
|
+
builder (~> 3.1.0)
|
10
|
+
erubis (~> 2.7.0)
|
11
|
+
rack (~> 1.5.2)
|
12
|
+
rack-test (~> 0.6.2)
|
13
|
+
activemodel (4.0.0)
|
14
|
+
activesupport (= 4.0.0)
|
15
|
+
builder (~> 3.1.0)
|
16
|
+
activerecord (4.0.0)
|
17
|
+
activemodel (= 4.0.0)
|
18
|
+
activerecord-deprecated_finders (~> 1.0.2)
|
19
|
+
activesupport (= 4.0.0)
|
20
|
+
arel (~> 4.0.0)
|
21
|
+
activerecord-deprecated_finders (1.0.3)
|
22
|
+
activesupport (4.0.0)
|
23
|
+
i18n (~> 0.6, >= 0.6.4)
|
24
|
+
minitest (~> 4.2)
|
25
|
+
multi_json (~> 1.3)
|
26
|
+
thread_safe (~> 0.1)
|
27
|
+
tzinfo (~> 0.3.37)
|
28
|
+
addressable (2.3.5)
|
29
|
+
arel (4.0.0)
|
30
|
+
atomic (1.1.10)
|
31
|
+
builder (3.1.4)
|
32
|
+
diff-lcs (1.2.4)
|
33
|
+
erubis (2.7.0)
|
34
|
+
faraday (0.8.7)
|
35
|
+
multipart-post (~> 1.1)
|
36
|
+
generator_spec (0.9.0)
|
37
|
+
activerecord (>= 3.0, <= 4.0)
|
38
|
+
railties (>= 3.0, <= 4.0)
|
39
|
+
git (1.2.5)
|
40
|
+
github_api (0.10.1)
|
41
|
+
addressable
|
42
|
+
faraday (~> 0.8.1)
|
43
|
+
hashie (>= 1.2)
|
44
|
+
multi_json (~> 1.4)
|
45
|
+
nokogiri (~> 1.5.2)
|
46
|
+
oauth2
|
47
|
+
hashie (2.0.5)
|
48
|
+
highline (1.6.19)
|
49
|
+
hike (1.2.3)
|
50
|
+
httpauth (0.2.0)
|
51
|
+
i18n (0.6.4)
|
52
|
+
jeweler (1.8.6)
|
53
|
+
builder
|
54
|
+
bundler (~> 1.0)
|
55
|
+
git (>= 1.2.5)
|
56
|
+
github_api (= 0.10.1)
|
57
|
+
highline (>= 1.6.15)
|
58
|
+
nokogiri (= 1.5.10)
|
59
|
+
rake
|
60
|
+
rdoc
|
61
|
+
json (1.8.0)
|
62
|
+
json_pure (1.8.0)
|
63
|
+
jwt (0.1.8)
|
64
|
+
multi_json (>= 1.5)
|
65
|
+
mail (2.5.4)
|
66
|
+
mime-types (~> 1.16)
|
67
|
+
treetop (~> 1.4.8)
|
68
|
+
mime-types (1.23)
|
69
|
+
minitest (4.7.5)
|
70
|
+
multi_json (1.7.7)
|
71
|
+
multi_xml (0.5.4)
|
72
|
+
multipart-post (1.2.0)
|
73
|
+
nokogiri (1.5.10)
|
74
|
+
oauth2 (0.9.2)
|
75
|
+
faraday (~> 0.8)
|
76
|
+
httpauth (~> 0.2)
|
77
|
+
jwt (~> 0.1.4)
|
78
|
+
multi_json (~> 1.0)
|
79
|
+
multi_xml (~> 0.5)
|
80
|
+
rack (~> 1.2)
|
81
|
+
polyglot (0.3.3)
|
82
|
+
rack (1.5.2)
|
83
|
+
rack-test (0.6.2)
|
84
|
+
rack (>= 1.0)
|
85
|
+
rails (4.0.0)
|
86
|
+
actionmailer (= 4.0.0)
|
87
|
+
actionpack (= 4.0.0)
|
88
|
+
activerecord (= 4.0.0)
|
89
|
+
activesupport (= 4.0.0)
|
90
|
+
bundler (>= 1.3.0, < 2.0)
|
91
|
+
railties (= 4.0.0)
|
92
|
+
sprockets-rails (~> 2.0.0)
|
93
|
+
railties (4.0.0)
|
94
|
+
actionpack (= 4.0.0)
|
95
|
+
activesupport (= 4.0.0)
|
96
|
+
rake (>= 0.8.7)
|
97
|
+
thor (>= 0.18.1, < 2.0)
|
98
|
+
rake (10.1.0)
|
99
|
+
rdoc (4.0.1)
|
100
|
+
json (~> 1.4)
|
101
|
+
rspec (2.13.0)
|
102
|
+
rspec-core (~> 2.13.0)
|
103
|
+
rspec-expectations (~> 2.13.0)
|
104
|
+
rspec-mocks (~> 2.13.0)
|
105
|
+
rspec-core (2.13.1)
|
106
|
+
rspec-expectations (2.13.0)
|
107
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
108
|
+
rspec-mocks (2.13.1)
|
109
|
+
rspec-rails (2.13.2)
|
110
|
+
actionpack (>= 3.0)
|
111
|
+
activesupport (>= 3.0)
|
112
|
+
railties (>= 3.0)
|
113
|
+
rspec-core (~> 2.13.0)
|
114
|
+
rspec-expectations (~> 2.13.0)
|
115
|
+
rspec-mocks (~> 2.13.0)
|
116
|
+
simplecov (0.7.1)
|
117
|
+
multi_json (~> 1.0)
|
118
|
+
simplecov-html (~> 0.7.1)
|
119
|
+
simplecov-html (0.7.1)
|
120
|
+
sprockets (2.10.0)
|
121
|
+
hike (~> 1.2)
|
122
|
+
multi_json (~> 1.0)
|
123
|
+
rack (~> 1.0)
|
124
|
+
tilt (~> 1.1, != 1.3.0)
|
125
|
+
sprockets-rails (2.0.0)
|
126
|
+
actionpack (>= 3.0)
|
127
|
+
activesupport (>= 3.0)
|
128
|
+
sprockets (~> 2.8)
|
129
|
+
sqlite3 (1.3.7)
|
130
|
+
thor (0.18.1)
|
131
|
+
thread_safe (0.1.0)
|
132
|
+
atomic
|
133
|
+
tilt (1.4.1)
|
134
|
+
treetop (1.4.14)
|
135
|
+
polyglot
|
136
|
+
polyglot (>= 0.3.1)
|
137
|
+
tzinfo (0.3.37)
|
138
|
+
|
139
|
+
PLATFORMS
|
140
|
+
ruby
|
141
|
+
|
142
|
+
DEPENDENCIES
|
143
|
+
actionpack (>= 4.0.0)
|
144
|
+
generator_spec
|
145
|
+
jeweler
|
146
|
+
json_pure
|
147
|
+
nokogiri
|
148
|
+
rails (>= 4.0.0)
|
149
|
+
rspec (>= 2.8.0)
|
150
|
+
rspec-rails (>= 2.8.0)
|
151
|
+
simplecov
|
152
|
+
sqlite3
|
data/History.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Change History / Release Notes
|
2
2
|
|
3
|
+
## Version 1.1.2
|
4
|
+
|
5
|
+
* pull #118 (thanks @ahmozkya): remove the deprecated `.live` function, and use `.on` instead.
|
6
|
+
Note: at least jquery 1.7 is required now!
|
7
|
+
|
3
8
|
## Version 1.1.1
|
4
9
|
|
5
10
|
* added the to be added/deleted element to the event, this allows to add animations/actions onto them
|
data/README.markdown
CHANGED
@@ -2,81 +2,69 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/nathanvda/cocoon)
|
4
4
|
|
5
|
-
|
5
|
+
Cocoon makes it easier to handle nested forms.
|
6
6
|
|
7
|
-
Nested forms are forms that handle nested models and attributes in one form
|
8
|
-
|
7
|
+
Nested forms are forms that handle nested models and attributes in one form;
|
8
|
+
e.g. a project with its tasks or an invoice with its line items.
|
9
9
|
|
10
|
-
|
10
|
+
Cocoon is form builder-agnostic, so it works with standard Rails, [Formtastic](https://github.com/justinfrench/formtastic), or [SimpleForm](https://github.com/plataformatec/simple_form).
|
11
|
+
It is compatible with rails 3 and rails 4.
|
11
12
|
|
12
|
-
This project is not related to [Apache Cocoon](http://cocoon.apache.org/)
|
13
|
+
This project is not related to [Apache Cocoon](http://cocoon.apache.org/).
|
13
14
|
|
14
15
|
## Prerequisites
|
15
16
|
|
16
|
-
This gem
|
17
|
-
|
18
|
-
|
19
|
-
Furthermore i would advice you to use either formtastic or simple_form.
|
20
|
-
|
21
|
-
I have a sample project where I demonstrate the use of cocoon with formtastic.
|
17
|
+
This gem depends on jQuery, so it's most useful in a Rails 3 project where you are already using jQuery.
|
18
|
+
Furthermore, I would advise you to use either [Formtastic](https://github.com/justinfrench/formtastic) or [SimpleForm](https://github.com/plataformatec/simple_form).
|
22
19
|
|
23
20
|
## Installation
|
24
21
|
|
25
22
|
Inside your `Gemfile` add the following:
|
26
23
|
|
27
|
-
|
24
|
+
```ruby
|
28
25
|
gem "cocoon"
|
29
|
-
|
26
|
+
```
|
27
|
+
|
30
28
|
|
31
29
|
### Rails 3.1+
|
32
30
|
|
33
|
-
Add the following to `application.js` so it compiles to the
|
34
|
-
asset_pipeline
|
31
|
+
Add the following to `application.js` so it compiles to the asset pipeline:
|
35
32
|
|
36
|
-
|
33
|
+
```ruby
|
37
34
|
//= require cocoon
|
38
|
-
|
35
|
+
```
|
39
36
|
|
40
37
|
### Rails 3.0.x
|
41
38
|
|
42
39
|
If you are using Rails 3.0.x, you need to run the installation task (since rails 3.1 this is no longer needed):
|
43
40
|
|
44
|
-
|
41
|
+
```bash
|
45
42
|
rails g cocoon:install
|
46
|
-
|
43
|
+
```
|
47
44
|
|
48
|
-
This will install the
|
49
|
-
Inside your `application.html.haml` you will need to add below the default javascripts:
|
45
|
+
This will install the Cocoon JavaScript file. In your application layout, add the following below the default javascripts:
|
50
46
|
|
51
|
-
|
47
|
+
```haml
|
52
48
|
= javascript_include_tag :cocoon
|
53
|
-
|
54
|
-
|
55
|
-
or using erb, you write
|
56
|
-
|
57
|
-
````ruby
|
58
|
-
<%= javascript_include_tag :cocoon %>
|
59
|
-
````
|
60
|
-
|
61
|
-
That is all you need to do to start using it!
|
49
|
+
```
|
62
50
|
|
63
|
-
## Usage
|
51
|
+
## Basic Usage
|
64
52
|
|
65
|
-
Suppose you have a
|
53
|
+
Suppose you have a `Project` model:
|
66
54
|
|
67
|
-
|
55
|
+
```bash
|
68
56
|
rails g scaffold Project name:string description:string
|
69
|
-
|
57
|
+
```
|
70
58
|
|
71
|
-
|
59
|
+
And a project has many `tasks`:
|
72
60
|
|
73
|
-
|
74
|
-
rails g model Task description:string done:boolean
|
75
|
-
|
61
|
+
```bash
|
62
|
+
rails g model Task description:string done:boolean project:belongs_to
|
63
|
+
```
|
76
64
|
|
77
|
-
|
65
|
+
Your models are associated like this:
|
78
66
|
|
79
|
-
|
67
|
+
```ruby
|
80
68
|
class Project < ActiveRecord::Base
|
81
69
|
has_many :tasks
|
82
70
|
accepts_nested_attributes_for :tasks, :reject_if => :all_blank, :allow_destroy => true
|
@@ -85,19 +73,19 @@ end
|
|
85
73
|
class Task < ActiveRecord::Base
|
86
74
|
belongs_to :project
|
87
75
|
end
|
88
|
-
|
76
|
+
```
|
89
77
|
|
90
|
-
|
91
|
-
|
92
|
-
|
78
|
+
Now we want a project form where we can add and remove tasks dynamically.
|
79
|
+
To do this, we need the fields for a new or existing `task` to be defined in a partial
|
80
|
+
named `_task_fields.html`.
|
93
81
|
|
94
|
-
|
82
|
+
## Examples
|
95
83
|
|
96
|
-
###
|
84
|
+
### Formtastic
|
97
85
|
|
98
|
-
|
86
|
+
In our `projects/_form` partial we'd write:
|
99
87
|
|
100
|
-
|
88
|
+
```haml
|
101
89
|
= f.inputs do
|
102
90
|
= f.input :name
|
103
91
|
= f.input :description
|
@@ -109,27 +97,25 @@ Inside our `projects/_form` partial we then write:
|
|
109
97
|
= link_to_add_association 'add task', f, :tasks
|
110
98
|
= f.actions do
|
111
99
|
= f.action :submit
|
112
|
-
|
100
|
+
```
|
113
101
|
|
114
|
-
|
102
|
+
And in our `_task_fields` partial we'd write:
|
115
103
|
|
116
|
-
|
104
|
+
```haml
|
117
105
|
.nested-fields
|
118
106
|
= f.inputs do
|
119
107
|
= f.input :description
|
120
108
|
= f.input :done, :as => :boolean
|
121
109
|
= link_to_remove_association "remove task", f
|
122
|
-
|
123
|
-
|
124
|
-
That is all there is to it!
|
110
|
+
```
|
125
111
|
|
126
|
-
|
112
|
+
The example project [cocoon_formtastic_demo](https://github.com/nathanvda/cocoon_formtastic_demo) demonstrates this.
|
127
113
|
|
128
|
-
###
|
114
|
+
### SimpleForm
|
129
115
|
|
130
|
-
|
116
|
+
In our `projects/_form` partial we'd write:
|
131
117
|
|
132
|
-
|
118
|
+
```haml
|
133
119
|
= simple_form_for @project do |f|
|
134
120
|
= f.input :name
|
135
121
|
= f.input :description
|
@@ -140,25 +126,25 @@ Inside our `projects/_form` partial we then write:
|
|
140
126
|
.links
|
141
127
|
= link_to_add_association 'add task', f, :tasks
|
142
128
|
= f.submit
|
143
|
-
|
129
|
+
```
|
144
130
|
|
145
|
-
|
131
|
+
In our `_task_fields` partial we write:
|
146
132
|
|
147
|
-
|
133
|
+
```haml
|
148
134
|
.nested-fields
|
149
135
|
= f.input :description
|
150
136
|
= f.input :done, :as => :boolean
|
151
137
|
= link_to_remove_association "remove task", f
|
152
|
-
|
138
|
+
```
|
153
139
|
|
154
|
-
|
140
|
+
The example project [cocoon_simple_form_demo](https://github.com/nathanvda/cocoon_simple_form_demo) demonstrates this.
|
155
141
|
|
156
|
-
###
|
142
|
+
### Standard Rails forms
|
157
143
|
|
158
|
-
|
144
|
+
In our `projects/_form` partial we'd write:
|
159
145
|
|
160
|
-
|
161
|
-
|
146
|
+
```haml
|
147
|
+
= form_for @project do |f|
|
162
148
|
.field
|
163
149
|
= f.label :name
|
164
150
|
%br
|
@@ -174,11 +160,11 @@ Inside our `projects/_form` partial we then write:
|
|
174
160
|
.links
|
175
161
|
= link_to_add_association 'add task', f, :tasks
|
176
162
|
= f.submit
|
177
|
-
|
163
|
+
```
|
178
164
|
|
179
|
-
|
165
|
+
In our `_task_fields` partial we'd write:
|
180
166
|
|
181
|
-
|
167
|
+
```haml
|
182
168
|
.nested-fields
|
183
169
|
.field
|
184
170
|
= f.label :description
|
@@ -188,25 +174,23 @@ and inside the `_task_fields` partial we write:
|
|
188
174
|
= f.check_box :done
|
189
175
|
= f.label :done
|
190
176
|
= link_to_remove_association "remove task", f
|
191
|
-
|
192
|
-
|
193
|
-
I will provide a sample project later.
|
177
|
+
```
|
194
178
|
|
195
179
|
## How it works
|
196
180
|
|
197
|
-
|
181
|
+
Cocoon defines two helper functions:
|
198
182
|
|
199
183
|
### link_to_add_association
|
200
184
|
|
201
|
-
This function
|
202
|
-
This should be
|
185
|
+
This function adds a link to your markup that, when clicked, dynamically adds a new partial form for the given association.
|
186
|
+
This should be called within the form builder.
|
203
187
|
|
204
|
-
|
188
|
+
`link_to_add_association` takes four parameters:
|
205
189
|
|
206
190
|
- name: the text to show in the link
|
207
|
-
- f:
|
191
|
+
- f: the form builder
|
208
192
|
- association: the name of the association (plural) of which a new instance needs to be added (symbol or string).
|
209
|
-
- html_options: extra html-options (see `link_to`)
|
193
|
+
- html_options: extra html-options (see [`link_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to)
|
210
194
|
There are some special options, the first three allow to control the placement of the new link-data:
|
211
195
|
- `data-association-insertion-traversal` : the jquery traversal method to allow node selection relative to the link. `closest`, `next`, `children`, etc. Default: absolute selection
|
212
196
|
- `data-association-insertion-node` : the jquery selector of the node
|
@@ -219,41 +203,45 @@ It takes four parameters:
|
|
219
203
|
- `wrap_object` : a proc that will allow to wrap your object, especially useful if you are using decorators (e.g. draper). See example lower.
|
220
204
|
- `force_non_association_create`: if true, it will _not_ create the new object using the association (see lower)
|
221
205
|
|
222
|
-
Optionally you
|
206
|
+
Optionally, you can omit the name and supply a block that is captured to render the link body (if you want to do something more complicated).
|
223
207
|
|
224
208
|
#### :render_options
|
225
|
-
Inside the `html_options` you can add an option `:render_options`, and the containing hash will be handed down to the form
|
226
|
-
form.
|
227
|
-
be handed down as follows:
|
209
|
+
Inside the `html_options` you can add an option `:render_options`, and the containing hash will be handed down to the form builder for the inserted
|
210
|
+
form.
|
228
211
|
|
229
|
-
|
212
|
+
When using Twitter Bootstrap and SimpleForm together, `simple_fields_for` needs the option `:wrapper => 'inline'` which can
|
213
|
+
be handed down as follows:
|
230
214
|
|
231
|
-
|
232
|
-
= link_to_add_association 'add something', f, :something, :render_options => {:wrapper => 'inline' }
|
233
|
-
````
|
215
|
+
(Note: In certain newer versions of simple_form, the option to use is `:wrapper => 'bootstrap'`.)
|
234
216
|
|
235
|
-
|
217
|
+
```haml
|
218
|
+
= link_to_add_association 'add something', f, :something,
|
219
|
+
:render_options => {:wrapper => 'inline' }
|
220
|
+
```
|
236
221
|
|
237
|
-
|
238
|
-
= link_to_add_association 'add something', f, :something, :render_options => {:locals => {:sherlock => 'Holmes' }}
|
239
|
-
````
|
222
|
+
To specify locals that needed to handed down to the partial:
|
240
223
|
|
224
|
+
```haml
|
225
|
+
= link_to_add_association 'add something', f, :something,
|
226
|
+
:render_options => {:locals => {:sherlock => 'Holmes' }}
|
227
|
+
```
|
241
228
|
|
242
229
|
#### :partial
|
243
230
|
|
244
|
-
To
|
231
|
+
To override the default partial name, e.g. because it shared between multiple views:
|
245
232
|
|
246
|
-
|
247
|
-
= link_to_add_association 'add something', f, :something,
|
248
|
-
|
233
|
+
```haml
|
234
|
+
= link_to_add_association 'add something', f, :something,
|
235
|
+
:partial => 'shared/something_fields'
|
236
|
+
```
|
249
237
|
|
250
238
|
#### :wrap_object
|
251
239
|
|
252
|
-
If you are using decorators, the normal instantiation of the associated will not be enough
|
240
|
+
If you are using decorators, the normal instantiation of the associated object will not be enough. You actually want to generate the decorated object.
|
253
241
|
|
254
242
|
A simple decorator would look like:
|
255
243
|
|
256
|
-
```
|
244
|
+
```ruby
|
257
245
|
class CommentDecorator
|
258
246
|
def initialize(comment)
|
259
247
|
@comment = comment
|
@@ -273,10 +261,11 @@ class CommentDecorator
|
|
273
261
|
end
|
274
262
|
```
|
275
263
|
|
276
|
-
To use this
|
264
|
+
To use this:
|
277
265
|
|
278
|
-
```
|
279
|
-
link_to_add_association('add something', @form_obj, :comments,
|
266
|
+
```haml
|
267
|
+
= link_to_add_association('add something', @form_obj, :comments,
|
268
|
+
:wrap_object => Proc.new {|comment| CommentDecorator.new(comment) })
|
280
269
|
```
|
281
270
|
|
282
271
|
Note that the `:wrap_object` expects an object that is _callable_, so any `Proc` will do. So you could as well use it to do some fancy extra initialisation (if needed).
|
@@ -284,9 +273,9 @@ But note you will have to return the (nested) object you want used.
|
|
284
273
|
E.g.
|
285
274
|
|
286
275
|
|
287
|
-
```
|
288
|
-
link_to_add_association('add something', @form_obj, :comments,
|
289
|
-
|
276
|
+
```haml
|
277
|
+
= link_to_add_association('add something', @form_obj, :comments,
|
278
|
+
:wrap_object => Proc.new { |comment| comment.name = current_user.name; comment })
|
290
279
|
```
|
291
280
|
|
292
281
|
#### :force_non_association_create
|
@@ -297,10 +286,11 @@ a new nested object. But this has a side-effect: for each call of `link_to_add_a
|
|
297
286
|
In most cases this is not a problem, but if you want to render a `link_to_add_association` for each nested element this will result
|
298
287
|
in an infinite loop.
|
299
288
|
|
300
|
-
To resolve this, specify that `:force_non_association_create` should be `true
|
289
|
+
To resolve this, specify that `:force_non_association_create` should be `true`:
|
301
290
|
|
302
|
-
```
|
303
|
-
link_to_add_association('add something', @form_obj, :comments,
|
291
|
+
```haml
|
292
|
+
= link_to_add_association('add something', @form_obj, :comments,
|
293
|
+
:force_non_association_create => true)
|
304
294
|
```
|
305
295
|
|
306
296
|
By default `:force_non_association_create` is `false`.
|
@@ -309,7 +299,7 @@ By default `:force_non_association_create` is `false`.
|
|
309
299
|
|
310
300
|
### link_to_remove_association
|
311
301
|
|
312
|
-
This function will add a link to your markup that
|
302
|
+
This function will add a link to your markup that, when clicked, dynamically removes the surrounding partial form.
|
313
303
|
This should be placed inside the partial `_<association-object-singular>_fields`.
|
314
304
|
|
315
305
|
It takes three parameters:
|
@@ -330,96 +320,91 @@ On insertion or removal the following events are triggered:
|
|
330
320
|
* `cocoon:before-remove`: called before removing the nested child
|
331
321
|
* `cocoon:after-remove`: called after removal
|
332
322
|
|
333
|
-
To listen to the events
|
323
|
+
To listen to the events in your JavaScript:
|
334
324
|
|
335
|
-
|
336
|
-
|
337
|
-
|
325
|
+
```javascript
|
326
|
+
$('#container').bind('cocoon:before-insert', function(e, insertedItem) {
|
327
|
+
// ... do something
|
328
|
+
});
|
329
|
+
```
|
338
330
|
|
339
|
-
where `e` is the event and the second parameter is the inserted or removed item. This allows you to change markup, or
|
331
|
+
...where `e` is the event and the second parameter is the inserted or removed item. This allows you to change markup, or
|
340
332
|
add effects/animations (see example below).
|
341
333
|
|
342
334
|
|
343
|
-
If in your view you have the following snippet to select an `owner
|
344
|
-
(we use slim for demonstration purposes)
|
335
|
+
If in your view you have the following snippet to select an `owner`:
|
345
336
|
|
346
|
-
|
337
|
+
```haml
|
347
338
|
#owner
|
348
339
|
#owner_from_list
|
349
340
|
= f.association :owner, :collection => Person.all(:order => 'name'), :prompt => 'Choose an existing owner'
|
350
341
|
= link_to_add_association 'add a new person as owner', f, :owner
|
351
|
-
|
352
|
-
|
353
|
-
This view part will either let you select an owner from the list of persons, or show the fields to add a new person as owner.
|
342
|
+
```
|
354
343
|
|
344
|
+
This will either let you select an owner from the list of persons, or show the fields to add a new person as owner.
|
355
345
|
|
356
346
|
The callbacks can be added as follows:
|
357
347
|
|
358
|
-
|
348
|
+
```javascript
|
359
349
|
$(document).ready(function() {
|
360
|
-
$('#owner')
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
function() {
|
376
|
-
/* e.g. recalculate order of child items */
|
377
|
-
});
|
350
|
+
$('#owner')
|
351
|
+
.bind('cocoon:before-insert', function() {
|
352
|
+
$("#owner_from_list").hide();
|
353
|
+
$("#owner a.add_fields").hide();
|
354
|
+
})
|
355
|
+
.bind('cocoon:after-insert', function() {
|
356
|
+
/* ... do something ... */
|
357
|
+
})
|
358
|
+
.bind("cocoon:before-remove", function() {
|
359
|
+
$("#owner_from_list").show();
|
360
|
+
$("#owner a.add_fields").show();
|
361
|
+
})
|
362
|
+
.bind("cocoon:after-remove", function() {
|
363
|
+
/* e.g. recalculate order of child items */
|
364
|
+
});
|
378
365
|
|
379
366
|
// example showing manipulating the inserted/removed item
|
380
367
|
|
381
|
-
$('#tasks')
|
368
|
+
$('#tasks')
|
369
|
+
.bind('cocoon:before-insert', function(e,task_to_be_added) {
|
382
370
|
task_to_be_added.fadeIn('slow');
|
383
|
-
|
384
|
-
|
385
|
-
$('#tasks').bind('cocoon:after-insert', function(e, added_task) {
|
371
|
+
})
|
372
|
+
.bind('cocoon:after-insert', function(e, added_task) {
|
386
373
|
// e.g. set the background of inserted task
|
387
374
|
added_task.css("background","red");
|
388
|
-
|
389
|
-
|
390
|
-
$('#tasks').bind('cocoon:before-remove', function(e, task) {
|
375
|
+
})
|
376
|
+
.bind('cocoon:before-remove', function(e, task) {
|
391
377
|
// allow some time for the animation to complete
|
392
378
|
$(this).data('remove-timeout', 1000);
|
393
379
|
task.fadeOut('slow');
|
394
|
-
|
395
|
-
|
396
|
-
|
380
|
+
});
|
397
381
|
});
|
398
|
-
|
399
|
-
|
400
|
-
Do note that for the callbacks to work there has to be a surrounding container (div), where you can bind the callbacks to.
|
382
|
+
```
|
401
383
|
|
384
|
+
Note that for the callbacks to work there has to be a surrounding container to which you can bind the callbacks.
|
402
385
|
|
403
386
|
When adding animations and effects to make the removal of items more interesting, you will also have to provide a timeout.
|
404
387
|
This is accomplished by the following line:
|
405
388
|
|
406
|
-
|
389
|
+
```javascript
|
390
|
+
$(this).data('remove-timeout', 1000);
|
391
|
+
```
|
407
392
|
|
408
|
-
|
393
|
+
You could also immediately add this to your view (on the `.nested-fields` container).
|
409
394
|
|
410
|
-
### Control the Insertion
|
395
|
+
### Control the Insertion Behaviour
|
411
396
|
|
412
|
-
The default insertion location is at the back of the current container. But we have added two `data
|
397
|
+
The default insertion location is at the back of the current container. But we have added two `data-` attributes that are read to determine the insertion-node and -method.
|
413
398
|
|
414
399
|
For example:
|
415
400
|
|
416
|
-
|
401
|
+
```javascript
|
417
402
|
$(document).ready(function() {
|
418
403
|
$("#owner a.add_fields").
|
419
404
|
data("association-insertion-method", 'before').
|
420
405
|
data("association-insertion-node", 'this');
|
421
406
|
});
|
422
|
-
|
407
|
+
```
|
423
408
|
|
424
409
|
The `association-insertion-node` will determine where to add it. You can choose any selector here, or specify this (default it is the parent-container).
|
425
410
|
|
@@ -429,27 +414,24 @@ The `association-insertion-traversal` will allow node selection to be relative t
|
|
429
414
|
|
430
415
|
For example:
|
431
416
|
|
432
|
-
|
417
|
+
```javascript
|
433
418
|
$(document).ready(function() {
|
434
419
|
$("#owner a.add_fields").
|
435
420
|
data("association-insertion-method", 'append').
|
436
421
|
data("association-insertion-traversal", 'closest').
|
437
422
|
data("association-insertion-node", '#parent_table');
|
438
423
|
});
|
439
|
-
|
424
|
+
```
|
440
425
|
|
441
426
|
### Partial
|
442
427
|
|
443
|
-
If no explicit partial
|
444
|
-
To override the default partial
|
445
|
-
|
446
|
-
For the javascript to behave correctly, the partial should start with a container (e.g. `div`) of class `.nested-fields`.
|
447
|
-
|
428
|
+
If no explicit partial name is given, `cocoon` looks for a file named `_<association-object_singular>_fields`.
|
429
|
+
To override the default partial use the `:partial` option.
|
448
430
|
|
431
|
+
For the JavaScript to behave correctly, the partial should start with a container (e.g. `div`) of class `.nested-fields`.
|
449
432
|
|
450
433
|
There is no limit to the amount of nesting, though.
|
451
434
|
|
452
|
-
|
453
435
|
## Note on Patches/Pull Requests
|
454
436
|
|
455
437
|
* Fork the project.
|
@@ -463,9 +445,8 @@ There is no limit to the amount of nesting, though.
|
|
463
445
|
|
464
446
|
## Contributors
|
465
447
|
|
466
|
-
The list of contributors just keeps on growing. [Check it out](https://github.com/nathanvda/cocoon/graphs/contributors)
|
467
|
-
I would really really like to thank all of them
|
468
|
-
they make cocoon more awesome every day. Thanks.
|
448
|
+
The list of contributors just keeps on growing. [Check it out!](https://github.com/nathanvda/cocoon/graphs/contributors)
|
449
|
+
I would really really like to thank all of them. They make cocoon more awesome every day. Thanks.
|
469
450
|
|
470
451
|
## Todo
|
471
452
|
|