rondo_form 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +47 -9
- data/lib/generators/rondo_form/install_generator.rb +2 -2
- data/lib/generators/rondo_form/templates/nested_rondo_controller.js +41 -0
- data/lib/rondo_form/version.rb +1 -1
- data/lib/rondo_form/view_helpers.rb +18 -21
- metadata +3 -3
- data/lib/generators/rondo_form/templates/cocoon_controller.js +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3d9a9ef19130de5f6aa92adf1139711bd5faaae4ef20155579e6865f291b7d9
|
4
|
+
data.tar.gz: 791d1fff3244853568a449b8b3c7a151dec19b45d2c3e2e79dd77cdec47ad891
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e511697842f4cebf817bf61108e0556281e0702b7acd9cb6b75c0ba62d18ae7ef33b3e2665ec240a595955d0d80c77d6297bd882a7de5148552997b1020e77d5
|
7
|
+
data.tar.gz: b9d9ef124e278eef3de87275295783874535207bd4785cac54a84059f28cd350e96f6b301399a1080e3ac63ab855370983c8b3793a86daf7fdd75a1c083929c2
|
data/README.md
CHANGED
@@ -8,24 +8,62 @@ Install the gem and add to the application's Gemfile by executing:
|
|
8
8
|
|
9
9
|
$ bundle add rondo_form
|
10
10
|
|
11
|
-
|
11
|
+
Or inside the Gemfile add the following
|
12
12
|
|
13
|
-
$ gem
|
13
|
+
$ gem 'rondo_form', '~> 0.2.0'
|
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, we have `Project` model, which has `has_many` relationship with `Task` model:
|
22
|
+
```
|
23
|
+
rails g scaffold Project name:string description:string
|
24
|
+
rails g model Task description:string done:boolean project:belongs_to
|
25
|
+
```
|
26
|
+
|
27
|
+
### Sample with SimpleForm
|
28
|
+
In your `projects/_form` partial:
|
29
|
+
``` erb
|
30
|
+
<%= simple_form_for(@project) do |f| %>
|
31
|
+
|
32
|
+
<div class="form-inputs">
|
33
|
+
<%= f.input :name %>
|
34
|
+
<%= f.input :description %>
|
35
|
+
</div>
|
36
|
+
|
37
|
+
<h3 class="text-xl mt-4">Tasks</h3>
|
38
|
+
<div class="my-2" data-controller="cocoon">
|
39
|
+
<%= f.simple_fields_for :tasks do |task| %>
|
40
|
+
<%= render "task_fields", f: task %>
|
41
|
+
<% end %>
|
42
|
+
<div class="links">
|
43
|
+
<%= link_to_add_association "Add Task", f, :tasks %>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<div class="form-actions mt-4">
|
48
|
+
<%= f.button :submit %>
|
49
|
+
</div>
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
```
|
53
|
+
|
54
|
+
In your `_task_fields` partial:
|
55
|
+
``` erb
|
56
|
+
<div class="nested-fields">
|
57
|
+
<%= f.input :description %>
|
58
|
+
<%= f.input :done, as: :boolean %>
|
59
|
+
<%= link_to_remove_association "Remove Task", f %>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
```
|
63
|
+
|
64
|
+
_Note_: You must add `data-controller="cocoon"` to an element, that wraps `fields_for` and `link_to_add_association` helper.
|
21
65
|
|
22
66
|
|
23
|
-
## Development
|
24
|
-
|
25
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
26
|
-
|
27
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
28
|
-
|
29
67
|
## Contributing
|
30
68
|
|
31
69
|
Bug reports and pull requests are welcome on GitHub at https://github.com/hungle00/rondo_form.
|
@@ -5,10 +5,10 @@ module RondoForm
|
|
5
5
|
desc "This generator installs the javascript needed for rondo_form"
|
6
6
|
|
7
7
|
def copy_the_javascript
|
8
|
-
copy_file "
|
8
|
+
copy_file "nested_rondo_controller.js", "app/javascript/controllers/nested_rondo_controller.js", force: true
|
9
9
|
if (Rails.root.join("app/javascript/controllers/index.js")).exist?
|
10
10
|
append_to_file "app/javascript/controllers/index.js",
|
11
|
-
%(import
|
11
|
+
%(import NestedRondoController from "./nested_rondo_controller"\napplication.register("nested-rondo", NestedRondoController)\n)
|
12
12
|
else
|
13
13
|
say %(Couldn't find "app/javascript/controllers/index.js".), :red
|
14
14
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["template"]
|
5
|
+
|
6
|
+
addField(e) {
|
7
|
+
e.preventDefault();
|
8
|
+
|
9
|
+
let assoc = e.target.dataset.association;
|
10
|
+
let newField = this.buildNewAssociation(assoc);
|
11
|
+
let insertionNode = this.templateTarget.parentElement;
|
12
|
+
insertionNode.insertAdjacentHTML("beforebegin", newField);
|
13
|
+
}
|
14
|
+
|
15
|
+
removeField(e) {
|
16
|
+
e.preventDefault();
|
17
|
+
|
18
|
+
let wrapperClass = this.data.get("wrapperClass") || "nested-fields";
|
19
|
+
let wrapperField = e.target.closest("." + wrapperClass);
|
20
|
+
if(e.target.matches('.dynamic')) {
|
21
|
+
wrapperField.remove();
|
22
|
+
} else {
|
23
|
+
wrapperField.querySelector("input[name*='_destroy']").value = 1;
|
24
|
+
wrapperField.style.display = "none";
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
buildNewAssociation(assoc) {
|
29
|
+
let content = this.templateTarget.innerHTML;
|
30
|
+
let regexpBraced = new RegExp('\\[new_' + assoc + '\\]', 'g');
|
31
|
+
let newId = new Date().getTime();
|
32
|
+
let newContent = content.replace(regexpBraced, '[' + newId + ']');
|
33
|
+
|
34
|
+
if (newContent == content) {
|
35
|
+
// assoc can be singular or plural
|
36
|
+
regexpBraced = new RegExp('\\[new_' + assoc + 's\\]', 'g');
|
37
|
+
newContent = content.replace(regexpBraced, '[' + newId + ']');
|
38
|
+
}
|
39
|
+
return newContent;
|
40
|
+
}
|
41
|
+
}
|
data/lib/rondo_form/version.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module RondoForm
|
2
2
|
module ViewHelpers
|
3
|
+
|
3
4
|
# this will show a link to remove the current association. This should be placed inside the partial.
|
4
5
|
# either you give
|
5
6
|
# - *name* : the text of the link
|
@@ -18,55 +19,51 @@ module RondoForm
|
|
18
19
|
name = capture(&block)
|
19
20
|
link_to_remove_association(name, f, html_options)
|
20
21
|
else
|
21
|
-
name
|
22
|
-
|
23
|
-
html_options = args[2] || {}
|
22
|
+
name, f, html_options = *args
|
23
|
+
html_options ||= {}
|
24
24
|
|
25
25
|
is_dynamic = f.object.new_record?
|
26
26
|
html_options[:class] = [html_options[:class], "remove_fields #{is_dynamic ? 'dynamic' : 'existing'}"].compact.join(' ')
|
27
|
-
html_options[:'data-action'] = "click->
|
27
|
+
html_options[:'data-action'] = "click->nested-rondo#removeField"
|
28
28
|
f.hidden_field(:_destroy) + link_to(name, '', html_options)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
# :nodoc:
|
33
|
-
def render_association(association, f, new_object)
|
34
|
-
f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
|
35
|
-
render(association.to_s.singularize + "_fields", :f => builder, :dynamic => true)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
32
|
# shows a link that will allow to dynamically add a new associated object.
|
40
33
|
#
|
41
34
|
# - *name* : the text to show in the link
|
42
|
-
# - *f* : the form this should come in
|
35
|
+
# - *f* : the form this should come in
|
43
36
|
# - *association* : the associated objects, e.g. :tasks, this should be the name of the <tt>has_many</tt> relation.
|
44
37
|
# - *html_options*: html options to be passed to <tt>link_to</tt> (see <tt>link_to</tt>)
|
45
38
|
# - *&block*: see <tt>link_to</tt>
|
46
39
|
|
47
40
|
def link_to_add_association(*args, &block)
|
48
41
|
if block_given?
|
49
|
-
f
|
50
|
-
|
51
|
-
html_options = args[2] || {}
|
42
|
+
f, association, html_options = *args
|
43
|
+
html_options ||= {}
|
52
44
|
link_to_add_association(capture(&block), f, association, html_options)
|
53
45
|
else
|
54
|
-
name
|
55
|
-
|
56
|
-
association = args[2]
|
57
|
-
html_options = args[3] || {}
|
46
|
+
name, f, association, html_options = *args
|
47
|
+
html_options ||= {}
|
58
48
|
|
59
49
|
html_options[:class] = [html_options[:class], "add_fields"].compact.join(' ')
|
60
50
|
html_options[:'data-association'] = association.to_s.singularize
|
61
|
-
html_options[:'data-action'] = "click->
|
51
|
+
html_options[:'data-action'] = "click->nested-rondo#addField"
|
62
52
|
|
63
53
|
new_object = f.object.class.reflect_on_association(association).klass.new
|
64
54
|
model_name = new_object.class.name.underscore
|
65
|
-
hidden_div = content_tag("template", id: "#{model_name}_fields_template", data: {
|
55
|
+
hidden_div = content_tag("template", id: "#{model_name}_fields_template", data: {'nested-rondo_target': 'template'}) do
|
66
56
|
render_association(association, f, new_object)
|
67
57
|
end
|
68
58
|
end
|
69
59
|
hidden_div.html_safe + link_to(name, '', html_options )
|
70
60
|
end
|
61
|
+
|
62
|
+
# :nodoc:
|
63
|
+
def render_association(association, f, new_object)
|
64
|
+
f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
|
65
|
+
render(association.to_s.singularize + "_fields", :f => builder, :dynamic => true)
|
66
|
+
end
|
67
|
+
end
|
71
68
|
end
|
72
69
|
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.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hungle00
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-06-
|
11
|
+
date: 2023-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -78,7 +78,7 @@ files:
|
|
78
78
|
- README.md
|
79
79
|
- Rakefile
|
80
80
|
- lib/generators/rondo_form/install_generator.rb
|
81
|
-
- lib/generators/rondo_form/templates/
|
81
|
+
- lib/generators/rondo_form/templates/nested_rondo_controller.js
|
82
82
|
- lib/rondo_form.rb
|
83
83
|
- lib/rondo_form/version.rb
|
84
84
|
- lib/rondo_form/view_helpers.rb
|
@@ -1,35 +0,0 @@
|
|
1
|
-
import { Controller } from "@hotwired/stimulus"
|
2
|
-
|
3
|
-
export default class extends Controller {
|
4
|
-
static targets = ["template"]
|
5
|
-
|
6
|
-
addField(e) {
|
7
|
-
e.preventDefault()
|
8
|
-
let assoc = e.target.dataset.association
|
9
|
-
let newField = this.buildNewAssociation(assoc)
|
10
|
-
let insertionNode = this.templateTarget.parentElement
|
11
|
-
insertionNode.insertAdjacentHTML("beforebegin", newField)
|
12
|
-
}
|
13
|
-
|
14
|
-
removeField(e) {
|
15
|
-
e.preventDefault()
|
16
|
-
let closestField = e.target.closest(".nested-fields")
|
17
|
-
if(e.target.matches('.dynamic')) {
|
18
|
-
closestField.remove()
|
19
|
-
} else {
|
20
|
-
closestField.style.display = "none"
|
21
|
-
}
|
22
|
-
}
|
23
|
-
|
24
|
-
buildNewAssociation(assoc) {
|
25
|
-
let content = this.templateTarget.innerHTML;
|
26
|
-
let regexp_braced = new RegExp('\\[new_' + assoc + '\\]', 'g');
|
27
|
-
let new_id = new Date().getTime();
|
28
|
-
let new_content = content.replace(regexp_braced, '[' + new_id + ']');
|
29
|
-
if (new_content == content) {
|
30
|
-
regexp_braced = new RegExp('\\[new_' + assoc + 's\\]', 'g');
|
31
|
-
new_content = content.replace(regexp_braced, '[' + new_id + ']');
|
32
|
-
}
|
33
|
-
return new_content
|
34
|
-
}
|
35
|
-
}
|