cool_nested_forms 2.0.1 → 2.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f3969154fb309fdbeb6d9b33aae0bfe3383f511d
4
- data.tar.gz: 17e7eddc9d7cc5afa7ec69b5ec45bdd66aa7fa15
3
+ metadata.gz: e5c86ef0d5b6bba5a5ed6ab919a29b88fea57e8d
4
+ data.tar.gz: 65c68db81d44c1ae8d4060383ee9edc9b0fe54d8
5
5
  SHA512:
6
- metadata.gz: cbf8acbb798e52da93f002bd04fd9b1e61587a652e91403c96f1d3c6755e910e171884a7af7f616ae81caf7087faade7affc33d106d6e1314620b9546f1a28a5
7
- data.tar.gz: 154c51f82021bd7fa9beb0c7c50ee413fc277262ca4c87f342b5ecbc0d795635ea92b7dc20715864ad0d748e96f19bbd85732122b70771de435065536f8d6dff
6
+ metadata.gz: 03bc77c8616c95989925cfef00ebe501ca63d132adb92b4313115225c3341c73c8577a46b96fa0d2e2ac32cd50badae248cf851361f91394e03c86de49032f41
7
+ data.tar.gz: 966e9e3ed104dfab84f5e6b50ccdf6a6a2267262a94418409368563a5707335c2ddd2d99d2c384c879558b1a945a186b014b4af6503e28f6f4ae0879e1ef5d08
data/README.md CHANGED
@@ -1,11 +1,16 @@
1
1
  # CoolNestedForms
2
2
  [![Gem Version](https://badge.fury.io/rb/cool_nested_forms.svg)](https://badge.fury.io/rb/cool_nested_forms)
3
3
 
4
- Add Nested Forms to your Forms. Currently tested with a depth of 2.
5
- For example a Form can add an Item and this Item can add a sub Item.
6
- It can probably support longer nests but I haven't tested it yet.
4
+ Add dynamically generated forms to your model's form for any of its associations.
5
+ For example if you have a Job model that has_many Task then this gem will assist you in adding
6
+ all the JavaScript necessary to allow your users to click an "Add Task" button on your edit view,
7
+ the view will then append a new form to the DOM with all the field attributes formatted for
8
+ rails (id, name, etc) plus will add any necessary hidden fields for existing records (task.id).
7
9
 
8
- By the way, this is intended to simplify adding the javascript required to add form_field dynamically while following form builder conventions. What that means is that there is some work to be done in the form of configuring models and controllers and adding a couple of views.
10
+ There is also JS events raised when an entry is added or removed so you can hook up your code for
11
+ pre-form submission editing.
12
+
13
+ Any entries added or removed won't update the DB until the form is submitted.
9
14
 
10
15
  ## Installation
11
16
 
@@ -23,7 +28,7 @@ Or install it yourself as:
23
28
 
24
29
  $ gem install cool_nested_forms
25
30
 
26
- Then require the javascript in your app/assets/javascripts/application.js
31
+ Then require the JavaScript in your app/assets/javascripts/application.js
27
32
  ```javascript
28
33
  //= require cool_nested_forms
29
34
  ```
@@ -35,22 +40,25 @@ For this example I will use Job and Task models
35
40
 
36
41
  #### Job Model
37
42
  ```ruby
38
- class Job < ActiveRecord::Base
43
+ class Job < ApplicationRecord
39
44
  has_many :tasks, :dependent => :destroy
40
- # :name is required - User your own required field here
45
+ # we need to accepts_nested_attributes_for Task
46
+ # :name is required in this example - Use your own required field here or remove the reject_if call
47
+ # :allow_destroy => true so we can delete entries when passing the _destroy field
41
48
  accepts_nested_attributes_for :tasks, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
42
49
  end
43
50
  ```
44
51
  #### Task Model
45
52
  ```ruby
46
- class Task < ActiveRecord::Base
53
+ class Task < ApplicationRecord
47
54
  belongs_to :job
48
55
  end
49
56
  ```
50
57
  ### Preparing the Job Controller
51
58
  ```ruby
52
59
  class JobsController < ApplicationController
53
-
60
+ # include the CoolNestedFormsHelper
61
+ helper CoolNestedFormsHelper
54
62
  # other code #
55
63
 
56
64
  def job_params
@@ -60,47 +68,75 @@ class JobsController < ApplicationController
60
68
  end
61
69
  end
62
70
  ```
63
- ### The view used to generate tasks
64
- Due to laziness remove_child_button needs to be nested right under the containing div. this will be fixed in the next version.
65
- app/views/jobs/_task.html.rb
66
- ```html
67
- <div>
68
- <%= remove_child_button "Remove" %>
69
- <%= f.hidden_field :_destroy, :class => 'removable' %>
70
-
71
- <%= f.label :name %>
72
- <%= f.text_field :name %>
71
+ ### The partials used to generate the new and existing tasks
72
+ We need to provide cool_nested_forms two partials. One for existing records and one
73
+ for existing records. They will be placed under the Job's view folder. Make sure the
74
+ id field of the container is set like so: id="<%= id %>"
75
+
76
+ app/views/jobs/_task_new.html.rb
77
+ ```erb
78
+ <!-- the id is generated from the helper methods using this template so always include it like so -->
79
+ <div id="<%= id %>">
80
+ <!-- _destroy field: used for removing the record -->
81
+ <%= builder.hidden_field :_destroy, :class => 'cnf-removable' %>
82
+
83
+ <!-- data to be collected -->
84
+ <%= builder.label :name %>
85
+ <%= builder.text_field :name %>
86
+
87
+ <!-- the remove button. make sure to pass the id as target or
88
+ it will default to the parent DOM element when removing the item -->
89
+ <%= remove_entry_button "Remove", Task, {:target => id} %>
90
+ </div>
91
+ ```
92
+ app/views/jobs/_task_edit.html.rb
93
+ ```erb
94
+ <!-- the id is generated from the helper methods using this template so always include it like so -->
95
+ <div id="<%= id %>">
96
+ <!-- _destroy field: used for removing the record -->
97
+ <%= builder.hidden_field :_destroy, :class => 'cnf-removable' %>
98
+ <%= builder.hidden_field :id %> <!-- keeps the id inside this div -->
99
+
100
+ <!-- data to be edited -->
101
+ <%= builder.label :name %>
102
+ <%= builder.text_field :name %>
103
+ <!-- Note: if you not wish for your users to edit this field after it is added
104
+ you could just display the content. -->
105
+
106
+ <!-- the remove button. make sure to pass the id as target or
107
+ it will default to the parent DOM element when removing the item -->
108
+ <%= remove_entry_button "Remove", Task, {:target => id} %>
73
109
  </div>
74
110
  ```
75
111
 
76
112
  ## Adding functionality to the Job form
77
113
  app/views/jobs/_form.html.erb
78
- ```html
79
- <%= form_for(@job) do |f| %>
80
-
114
+ ```erb
115
+ <%= form_with(model: job, local: true) do |form| %>
81
116
 
82
117
  <!-- your other job fields go here -->
83
118
 
119
+ <!-- this generates a template for JavaScript. Pass the Task model class here. -->
120
+ <%= new_entry_template(form,Task) %>
84
121
 
85
- <!-- this generates a template for javascript -->
86
- <%= new_fields_template f, :tasks, {object: Tasks.new, :template => "tasks_#{f.object.id}_fields"} %>
87
- <!-- this generates a button that adds a task into <div id="tasks_<%=f.object.id%>"> -->
88
- <%= add_child_button "Add Task", :tasks, "tasks_#{f.object.id}", "tasks_#{f.object.id}", "<your-css-classes>" %>
122
+ <!-- this generates a button that adds a task into <div id="tasks">. id="tasks"
123
+ is automatically generated by the next helper by convention. Pass the Task model class here. -->
124
+ <%= new_entry_button("Add Task", Task )%>
89
125
 
90
- <div id="tasks_<%=f.object.id%>">
91
- <%= f.fields_for :tasks, @job.tasks do |builder| %>
92
- <%= render "task", :f => builder %>
93
- <% end %>
94
- </div>
126
+ <!-- generates a container with any existing tasks. provides a location for
127
+ placing new tasks. The id of the container is by default <div id="tasks">
128
+ (the association plural form). Pass the Task model class here. -->
129
+ <%= entries_container(form,Task,job.tasks) %>
95
130
 
96
131
  <%end%>
97
132
  ```
98
133
 
99
134
  ### After add/remove events
100
- If you need to perform any other javascript actions after a child is added or removed, you can add a listener to these events
135
+ If you need to perform any other javascript actions after an entry is added or
136
+ removed, you can add a listener to these events
101
137
  ```javascript
102
- coolNestedForms.childAdded
103
- coolNestedForms.childRemoved
138
+ coolNestedForms.entryAdded
139
+ coolNestedForms.entryRemoved
104
140
  ```
105
141
  Something like this
106
142
  ```javascript
@@ -1,5 +1,45 @@
1
1
  module CoolNestedFormsHelper
2
+ ## entries_container ##
3
+ # arguments
4
+ # - builder: a FormBuilder Object obtained from form_with or form_for
5
+ # - association: a model class i.e. MyTask
6
+ # - current_entries: all the current entries for the parent i.e. a Form.tasks
7
+ # - options: hash of override options
8
+ # - partial: name of the erb partial to use as a tempalte for the existing entries
9
+ # - id: ID to be used in for the container
10
+ # - plurilized: the plural version of the model name
11
+ # - singularized: the singular version of the model name
12
+ # - parent_singularized: the name of the parent record. used for generating the entry's container id
13
+ # - parent_id: the id of the parent record. used for generating the entry's container id
14
+ # - class: a string with any css class names to be used for styling
15
+ # - style: a string with any css styles
16
+ # - tag: override the returned tag
17
+ def entries_container(builder,association,current_entries, options = {})
18
+ # initialize options
19
+ options[:partial] ||= "#{association.name.underscore}_edit"
20
+ options[:id] ||= association.name.underscore.pluralize
21
+ options[:pluralized] ||= association.name.underscore.pluralize
22
+ options[:singularized] ||= association.name.underscore
23
+ options[:parent_singularized] ||= builder.object.class.name.underscore
24
+ options[:parent_id] ||= builder.object.id.to_s
25
+ options[:class] ||= ''
26
+ options[:style] ||= ''
27
+ options[:tag] ||= :div
28
+
29
+ # render all the current entries
30
+ output = builder.fields_for(options[:pluralized], current_entries) do |assoc_builder|
31
+ id = "#{options[:parent_singularized]}_#{options[:parent_id]}_#{options[:singularized]}_#{assoc_builder.object.id}"
32
+ render options[:partial], :builder => assoc_builder, :id => id
33
+ end
2
34
 
35
+ return content_tag(
36
+ options[:tag],
37
+ output.html_safe,
38
+ :style => options[:style],
39
+ :class => options[:class],
40
+ :id => options[:id]
41
+ )
42
+ end
3
43
  ## new_entry_template ##
4
44
  # arguments
5
45
  # - builder: a FormBuilder Object obtained from form_with or form_for
@@ -12,7 +52,7 @@ module CoolNestedFormsHelper
12
52
  # - children: an array with childre association options for nested association of a nested association
13
53
  def new_entry_template(builder,association, options = {})
14
54
  # initialize options
15
- options[:partial] ||= association.name.underscore
55
+ options[:partial] ||= "#{association.name.underscore}_new"
16
56
  options[:id] ||= "#{association.name.underscore}_[tempid]"
17
57
  options[:pluralized] ||= association.name.underscore.pluralize
18
58
  options[:js_template_name] ||= association.name.underscore.pluralize
@@ -1,3 +1,3 @@
1
1
  module CoolNestedForms
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cool_nested_forms
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carlos Roque