rondo_form 0.2.5 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +73 -4
- data/lib/generators/rondo_form/templates/nested_rondo_controller.js +12 -6
- data/lib/rondo_form/version.rb +1 -1
- data/lib/rondo_form/view_helpers.rb +20 -12
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc37cc28bcea758383fa57af673206440f3d71413763fbc3bea157de11686787
|
4
|
+
data.tar.gz: 8d7e14c2d455fd0397aed863fc050bb70293a5045810c6ea4fbd16297faad9ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84788ef35f96668f52aefcbd5bc9428bd655b23fb172c5e21fc46d93af5a8393d531e1afc56e22c6ae038bf8b8ca89def4c9b0e652fcfde8027da68a8317f0e7
|
7
|
+
data.tar.gz: f2729cc3cda456f0a12ab1536cfed97c6c44ed53e6bef1bd7e1a052bd045c08a03c13ba4fb89399f36cd53050c1ad8e0fff50833ee35f5652416ebb758928006
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# 1.0.0
|
2
|
+
## Breaking Changes
|
3
|
+
- Add `render_options` as parameter to `link_to_add_association` [#10](https://github.com/hungle00/rondo_form/pull/10)
|
4
|
+
- Rename `partial_name` to `partial` to match Rails helper [#10](https://github.com/hungle00/rondo_form/pull/10)
|
5
|
+
|
6
|
+
## All Changes
|
7
|
+
- Add documentation of the view helpers to the README [#10](https://github.com/hungle00/rondo_form/pull/10)
|
data/README.md
CHANGED
@@ -10,22 +10,76 @@ Install the gem and add to the application's Gemfile by executing:
|
|
10
10
|
|
11
11
|
Or inside the Gemfile add the following
|
12
12
|
|
13
|
-
$ gem 'rondo_form', '~> 0.2.
|
13
|
+
$ gem 'rondo_form', '~> 0.2.6'
|
14
14
|
|
15
15
|
Run the installation task:
|
16
16
|
|
17
|
-
$ rails g rondo_form:install
|
17
|
+
$ rails g rondo_form:install
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
For example,
|
21
|
+
For example, you have `Project` model, which has `has_many` relationship with `Task` model:
|
22
|
+
|
22
23
|
```
|
23
24
|
rails g scaffold Project name:string description:string
|
24
25
|
rails g model Task description:string done:boolean project:belongs_to
|
25
26
|
```
|
26
27
|
|
28
|
+
You need to add `accepts_nested_attributes_for` to `Project` model:
|
29
|
+
|
30
|
+
```
|
31
|
+
class Project < ApplicationRecord
|
32
|
+
has_many :tasks, dependent: :destroy
|
33
|
+
accepts_nested_attributes_for :tasks, reject_if: :all_blank, allow_destroy: true
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
## View helpers
|
38
|
+
|
39
|
+
### `link_to_add_association(name, form_builder, render_options, html_options, &block)`
|
40
|
+
|
41
|
+
### Signatures
|
42
|
+
```ruby
|
43
|
+
link_to_add_association(name, form_builder, render_options, html_options)
|
44
|
+
# Link text is passed in as name
|
45
|
+
|
46
|
+
link_to_add_association(form_builder, render_options, html_options, &block)
|
47
|
+
# Link text is passed in as a block
|
48
|
+
```
|
49
|
+
|
50
|
+
### Options
|
51
|
+
- `render_options: hash containing options for Rails' render helper` - This is passed to the Rails `render` helper to
|
52
|
+
provide the options that are desired when rendering your association fields. If no special requirements are needed,
|
53
|
+
can be passed as `nil` or and empty hash `{}`.
|
54
|
+
|
55
|
+
- `html_options: hash containing options for Rails' link_to helper` - This is passed to the Rails `link_to` helper to
|
56
|
+
provide the options that are desired when rendering your association fields. If no special requirements are needed,
|
57
|
+
can be passed as `nil` or and empty hash `{}`.
|
58
|
+
|
59
|
+
### `link_to_remove_association(name, form_builder, html_options, &block)`
|
60
|
+
|
61
|
+
### Signatures
|
62
|
+
```ruby
|
63
|
+
link_to_remove_association(name, form_builder, html_options)
|
64
|
+
# Link text is passed in as name
|
65
|
+
|
66
|
+
link_to_remove_association(form_builder, html_options, &block)
|
67
|
+
# Link text is passed in as a block
|
68
|
+
```
|
69
|
+
|
70
|
+
### Options
|
71
|
+
|
72
|
+
- `html_options: hash containing options for Rails' link_to helper` - This is passed to the Rails `link_to` helper to
|
73
|
+
provide the options that are desired when rendering your association fields. If no special requirements are needed,
|
74
|
+
can be passed as `nil` or and empty hash `{}`.
|
75
|
+
|
27
76
|
### Sample with SimpleForm
|
77
|
+
|
78
|
+
The RondoForm gem adds two helper functions: `link_to_add_association` and `link_to_remove_association`.
|
79
|
+
The example below illustrates the way to use it.
|
80
|
+
|
28
81
|
In your `projects/_form` partial:
|
82
|
+
|
29
83
|
``` erb
|
30
84
|
<%= simple_form_for(@project) do |f| %>
|
31
85
|
|
@@ -50,23 +104,38 @@ In your `projects/_form` partial:
|
|
50
104
|
<%= f.button :submit %>
|
51
105
|
</div>
|
52
106
|
<% end %>
|
53
|
-
|
54
107
|
```
|
55
108
|
|
56
109
|
In your `_task_fields` partial:
|
110
|
+
|
57
111
|
``` erb
|
58
112
|
<div class="task-field">
|
59
113
|
<%= f.input :description %>
|
60
114
|
<%= f.input :done, as: :boolean %>
|
61
115
|
<%= link_to_remove_association "Remove Task", f %>
|
62
116
|
</div>
|
117
|
+
```
|
63
118
|
|
119
|
+
### Controller
|
120
|
+
|
121
|
+
Using projects example, in your controller ProjectsController, your params method should look like:
|
122
|
+
``` ruby
|
123
|
+
def project_params
|
124
|
+
params.require(:project).permit(:name, :description, tasks_attributes: [:description, :done, :_destroy, :id])
|
125
|
+
end
|
64
126
|
```
|
65
127
|
|
128
|
+
params `:_destroy` allow to delete tasks and `:id` allow to update tasks on update action
|
129
|
+
|
130
|
+
|
66
131
|
_Convention_:
|
132
|
+
|
67
133
|
- For convention, I named Stimulus controller `nested-rondo`. But you can change the name of Javascript file and the value of `data-controller` to match your purpose.
|
68
134
|
- `data-nested-rondo-target="fieldContain"` must be added to an element that wraps all nested fields, the new field will be appended to this element.
|
69
135
|
- `data-nested-rondo-field-class-value` is used to detect the element that needs to be removed. Its value must match the class name of an element that wraps the partial. If you do not declare it, it will default remove the closest parent element.
|
136
|
+
- The partial added when clicking `link_to_add_association` is named for the association name with the `_fields` suffix. In this example, the partial is named `task_fields`. You can change the partial name by passing the `partial_name` option to `link_to_add_association`.
|
137
|
+
|
138
|
+
View details implement for this sample at [rondo_form_demo_turbo_8](https://github.com/hungle00/turbo_8_demos/tree/rondo_form)
|
70
139
|
|
71
140
|
## Contributing
|
72
141
|
|
@@ -14,7 +14,7 @@ export default class extends Controller {
|
|
14
14
|
removeField(e) {
|
15
15
|
e.preventDefault();
|
16
16
|
const wrapperField = this.hasFieldClassValue ? e.target.closest("." + this.fieldClassValue) : e.target.parentNode;
|
17
|
-
|
17
|
+
|
18
18
|
if(e.target.matches('.dynamic')) {
|
19
19
|
wrapperField.remove();
|
20
20
|
} else {
|
@@ -23,17 +23,23 @@ export default class extends Controller {
|
|
23
23
|
}
|
24
24
|
}
|
25
25
|
|
26
|
-
buildNewAssociation(
|
27
|
-
|
28
|
-
|
26
|
+
buildNewAssociation(event) {
|
27
|
+
let element = event.target;
|
28
|
+
while (element) {
|
29
|
+
if (element.hasAttribute('data-association') || element.hasAttribute('data-associations'))
|
30
|
+
break
|
31
|
+
element = element.parentElement;
|
32
|
+
}
|
33
|
+
const assoc = element.dataset.association;
|
34
|
+
const assocs = element.dataset.associations;
|
29
35
|
const content = this.templateTarget.innerHTML;
|
30
|
-
|
36
|
+
|
31
37
|
let regexpBraced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g');
|
32
38
|
let newId = new Date().getTime();
|
33
39
|
let newContent = content.replace(regexpBraced, '[' + newId + ']$1');
|
34
40
|
|
35
41
|
if (newContent == content) {
|
36
|
-
// assoc can be singular or plural
|
42
|
+
// assoc can be singular or plural
|
37
43
|
regexpBraced = new RegExp('\\[new_' + assocs + '\\](.*?\\s)', 'g');
|
38
44
|
newContent = content.replace(regexpBraced, '[' + newId + ']$1');
|
39
45
|
}
|
data/lib/rondo_form/version.rb
CHANGED
@@ -11,7 +11,7 @@ module RondoForm
|
|
11
11
|
# - *f* : the form this link should be placed in
|
12
12
|
# - *html_options*: html options to be passed to link_to (see <tt>link_to</tt>)
|
13
13
|
# - *&block*: the output of the block will be show in the link, see <tt>link_to</tt>
|
14
|
-
|
14
|
+
|
15
15
|
def link_to_remove_association(*args, &block)
|
16
16
|
if block_given?
|
17
17
|
f = args.first
|
@@ -31,19 +31,24 @@ module RondoForm
|
|
31
31
|
|
32
32
|
# shows a link that will allow to dynamically add a new associated object.
|
33
33
|
#
|
34
|
-
# - *name* :
|
35
|
-
# - *f* :
|
36
|
-
# - *association* :
|
37
|
-
# - *
|
38
|
-
#
|
34
|
+
# - *name* : the text to show in the link
|
35
|
+
# - *f* : the form this should come in
|
36
|
+
# - *association* : the associated objects, e.g. :tasks, this should be the name of the <tt>has_many</tt> relation.
|
37
|
+
# - *render_options*: options to be passed to <tt>render</tt>
|
38
|
+
# - partial: 'file_name'
|
39
|
+
# - locals: { hash_of: 'local variables for rendered partial' }
|
40
|
+
# - *html_options*: html options to be passed to <tt>link_to</tt> (see <tt>link_to</tt>)
|
41
|
+
# - *&block*: see <tt>link_to</tt>
|
39
42
|
|
40
43
|
def link_to_add_association(*args, &block)
|
41
44
|
if block_given?
|
42
|
-
f, association, html_options = *args
|
45
|
+
f, association, render_options, html_options = *args
|
46
|
+
render_options ||= {}
|
43
47
|
html_options ||= {}
|
44
|
-
link_to_add_association(capture(&block), f, association, html_options)
|
48
|
+
link_to_add_association(capture(&block), f, association, render_options, html_options)
|
45
49
|
else
|
46
|
-
name, f, association, html_options = *args
|
50
|
+
name, f, association, render_options, html_options = *args
|
51
|
+
render_options ||= {}
|
47
52
|
html_options ||= {}
|
48
53
|
|
49
54
|
html_options[:class] = [html_options[:class], "add_fields"].compact.join(' ')
|
@@ -54,16 +59,19 @@ module RondoForm
|
|
54
59
|
new_object = f.object.class.reflect_on_association(association).klass.new
|
55
60
|
model_name = new_object.class.name.underscore
|
56
61
|
hidden_div = content_tag("template", id: "#{model_name}_fields_template", data: {'nested-rondo_target': 'template'}) do
|
57
|
-
render_association(association, f, new_object)
|
62
|
+
render_association(association, f, new_object, render_options)
|
58
63
|
end
|
59
64
|
hidden_div.html_safe + link_to(name, '', html_options )
|
60
65
|
end
|
61
66
|
end
|
62
67
|
|
63
68
|
# :nodoc:
|
64
|
-
def render_association(association, f, new_object)
|
69
|
+
def render_association(association, f, new_object, render_options)
|
70
|
+
locals = render_options.delete(:locals) || {}
|
71
|
+
render_options[:partial] = "#{association.to_s.singularize}_fields" unless render_options[:partial]
|
65
72
|
f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
|
66
|
-
|
73
|
+
locals.store(:f, builder)
|
74
|
+
render(render_options[:partial], locals)
|
67
75
|
end
|
68
76
|
end
|
69
77
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rondo_form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hungle00
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -72,6 +72,7 @@ extensions: []
|
|
72
72
|
extra_rdoc_files: []
|
73
73
|
files:
|
74
74
|
- ".rspec"
|
75
|
+
- CHANGELOG.md
|
75
76
|
- Gemfile
|
76
77
|
- Gemfile.lock
|
77
78
|
- LICENSE.txt
|
@@ -104,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
105
|
- !ruby/object:Gem::Version
|
105
106
|
version: '0'
|
106
107
|
requirements: []
|
107
|
-
rubygems_version: 3.
|
108
|
+
rubygems_version: 3.5.16
|
108
109
|
signing_key:
|
109
110
|
specification_version: 4
|
110
111
|
summary: Cocoon, but with Stimulus JS
|