view_component_reflex 1.2.0 → 1.6.1
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/README.md +123 -2
- data/app/components/view_component_reflex/component.rb +52 -7
- data/lib/view_component_reflex/version.rb +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2269d8639ced76028ffe2a5970960d7381c862a75ce36481a84d8cf8886acd6c
|
4
|
+
data.tar.gz: c368a487c3a2d97b4207ecb47558877596f9f9dccc7aa63f363598bc72a4eb82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4822e9370947d8881b8f33ca8a00df19a9458ca31f9da4bc84bcfb438e768f37226a2790f489efe94ec36418f77ed4d32a122a003653ec3120ddc49df5af2a1d
|
7
|
+
data.tar.gz: 0f38085c800aa78f43e6df67cec9664115fed2cbce0cefc7fb89dbe2a0b3f624d7adfff1a71e542039af40a6b247744677e96a0115afe6f5f5ad65fb4c2a78df
|
data/README.md
CHANGED
@@ -30,7 +30,7 @@ end
|
|
30
30
|
# counter_component.html.erb
|
31
31
|
<%= component_controller do %>
|
32
32
|
<p><%= @count %></p>
|
33
|
-
|
33
|
+
<%= reflex_tag :increment, :button, "Click" %>
|
34
34
|
<% end %>
|
35
35
|
```
|
36
36
|
|
@@ -39,7 +39,7 @@ end
|
|
39
39
|
In order to reconcile state to components in collections, you can specify a `collection_key` method that returns some
|
40
40
|
value unique to that component.
|
41
41
|
|
42
|
-
```
|
42
|
+
```ruby
|
43
43
|
class TodoComponent < ViewComponentReflex::Component
|
44
44
|
def initialize(todo:)
|
45
45
|
@todo = todo
|
@@ -59,6 +59,127 @@ end
|
|
59
59
|
If a new parameter is passed to the component during rendering, it is used instead of what's in state.
|
60
60
|
If you're storing instances in state, you can use this to properly compare them.
|
61
61
|
|
62
|
+
```ruby
|
63
|
+
def permit_parameter?(initial_param, new_param)
|
64
|
+
if new_param.instance_of? MyModel
|
65
|
+
new_param.id == @my_model.id
|
66
|
+
else
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
### omitted_from_state
|
73
|
+
Return an array of instance variables you want to omit from state. Useful if you have an object
|
74
|
+
that isn't serializable as an instance variable, like a form.
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
def omitted_from_state
|
78
|
+
[:@form]
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
### reflex_tag(reflex, name, content_or_options_with_block = nil, options = nil, escape = true, &block)
|
83
|
+
This shares the same definition as `content_tag`, except it accepts a reflex as the first parameter.
|
84
|
+
|
85
|
+
```erb
|
86
|
+
<%= reflex_tag :increment, :button, "Click me!" %>
|
87
|
+
```
|
88
|
+
|
89
|
+
Would add a click handler to the `increment` method on your component.
|
90
|
+
|
91
|
+
To use a non-click event, specific that with `->` notiation
|
92
|
+
|
93
|
+
```erb
|
94
|
+
<%= reflex_tag "mouseenter->increment", :button, "Click me!" %>
|
95
|
+
```
|
96
|
+
|
97
|
+
### collection_key
|
98
|
+
If you're rendering a component as a collection with `MyComponent.with_collection(SomeCollection)`, you must define this method to return some unique value for the component.
|
99
|
+
This is used to reconcile state in the background.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
def initialize
|
103
|
+
@my_model = MyModel.new
|
104
|
+
end
|
105
|
+
|
106
|
+
def collection_key
|
107
|
+
@my_model.id
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
### prevent_refresh!
|
112
|
+
By default, VCR will re-render your component after it executes your method. `revent_refresh!` prevents this from happening.
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
def my_method
|
116
|
+
prevent_refresh!
|
117
|
+
@foo = Lbar
|
118
|
+
end # the rendered page will not reflect this change
|
119
|
+
```
|
120
|
+
|
121
|
+
### refresh_all!
|
122
|
+
Refresh the entire body of the page
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
def do_some_global_action
|
126
|
+
prevent_refresh!
|
127
|
+
session[:model] = MyModel.new
|
128
|
+
refresh_all!
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
### key
|
133
|
+
This is a key unique to a particular component. It's used to reconcile state between renders, and should be passed as a data attribute whenever a reflex is called
|
134
|
+
|
135
|
+
```erb
|
136
|
+
<button type="button" data-reflex="click->MyComponent#do_something" data-key="<%= key %>">Click me!</button>
|
137
|
+
```
|
138
|
+
|
139
|
+
### component_controller(options = {}, &blk)
|
140
|
+
This is a view helper to properly connect VCR to the component. It outputs `<div data-controller="my-controller" key=<%= key %></div>`
|
141
|
+
You *must* wrap your component in this for everything to work properly.
|
142
|
+
|
143
|
+
```erb
|
144
|
+
<%= component_controller do %>
|
145
|
+
<p><%= @count %></p
|
146
|
+
<% end %>
|
147
|
+
```
|
148
|
+
|
149
|
+
## Common patterns
|
150
|
+
A lot of the time, you only need to update specific components when changing instance variables. For example, changing `@loading` might only need
|
151
|
+
to display a spinner somewhere on the page. You can define setters to implicitly render the appropriate pieces of dom whenever that variable is set
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
def initialize
|
155
|
+
@loading = false
|
156
|
+
end
|
157
|
+
|
158
|
+
def loading=(new_value)
|
159
|
+
@loading = new_value
|
160
|
+
refresh! '#loader'
|
161
|
+
end
|
162
|
+
|
163
|
+
def do_expensive_action
|
164
|
+
prevent_refresh!
|
165
|
+
|
166
|
+
self.loading = true
|
167
|
+
execute_it
|
168
|
+
self.loading = false
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
```erb
|
173
|
+
<%= component_controller do %>
|
174
|
+
<div id="loader">
|
175
|
+
<% if @loading %>
|
176
|
+
<p>Loading...</p>
|
177
|
+
<% end %>
|
178
|
+
</div>
|
179
|
+
|
180
|
+
<button type="button" data-reflex="click->MyComponent#do_expensive_action" data-key="<%= key %>">Click me!</button>
|
181
|
+
<% end
|
182
|
+
```
|
62
183
|
|
63
184
|
## Custom State Adapters
|
64
185
|
|
@@ -43,7 +43,11 @@ module ViewComponentReflex
|
|
43
43
|
component.instance_variable_set(k, v)
|
44
44
|
end
|
45
45
|
name.to_proc.call(component, *args)
|
46
|
-
refresh!
|
46
|
+
refresh! unless @prevent_refresh
|
47
|
+
end
|
48
|
+
|
49
|
+
def prevent_refresh!
|
50
|
+
@prevent_refresh = true
|
47
51
|
end
|
48
52
|
|
49
53
|
define_method :component_class do
|
@@ -62,7 +66,7 @@ module ViewComponentReflex
|
|
62
66
|
return @component if @component
|
63
67
|
@component = component_class.allocate
|
64
68
|
reflex = self
|
65
|
-
exposed_methods = [:params, :request, :element, :refresh!, :refresh_all!, :stimulus_controller]
|
69
|
+
exposed_methods = [:params, :request, :element, :refresh!, :refresh_all!, :stimulus_controller, :session, :prevent_refresh!]
|
66
70
|
exposed_methods.each do |meth|
|
67
71
|
@component.define_singleton_method(meth) do |*a|
|
68
72
|
reflex.send(meth, *a)
|
@@ -98,15 +102,23 @@ module ViewComponentReflex
|
|
98
102
|
helpers.controller.instance_variable_get(:@stimulus_reflex)
|
99
103
|
end
|
100
104
|
|
101
|
-
def component_controller(opts = {}, &blk)
|
105
|
+
def component_controller(opts_or_tag = :div, opts = {}, &blk)
|
102
106
|
self.class.init_stimulus_reflex
|
103
107
|
init_key
|
104
|
-
|
108
|
+
|
109
|
+
tag = :div
|
110
|
+
if opts_or_tag.is_a? Hash
|
111
|
+
options = opts_or_tag
|
112
|
+
else
|
113
|
+
tag = opts_or_tag
|
114
|
+
options = opts
|
115
|
+
end
|
116
|
+
options[:data] = {
|
105
117
|
controller: self.class.stimulus_controller,
|
106
118
|
key: key,
|
107
|
-
**(
|
119
|
+
**(options[:data] || {})
|
108
120
|
}
|
109
|
-
content_tag
|
121
|
+
content_tag tag, capture(&blk), options
|
110
122
|
end
|
111
123
|
|
112
124
|
# key is required if you're using state
|
@@ -121,6 +133,24 @@ module ViewComponentReflex
|
|
121
133
|
@key = key
|
122
134
|
end
|
123
135
|
|
136
|
+
def reflex_tag(reflex, name, content_or_options_with_block = {}, options = {}, escape = true, &block)
|
137
|
+
action, method = reflex.to_s.split("->")
|
138
|
+
if method.nil?
|
139
|
+
method = action
|
140
|
+
action = "click"
|
141
|
+
end
|
142
|
+
data_attributes = {
|
143
|
+
reflex: "#{action}->#{self.class.name}##{method}",
|
144
|
+
key: key
|
145
|
+
}
|
146
|
+
if content_or_options_with_block.is_a?(Hash)
|
147
|
+
merge_data_attributes(content_or_options_with_block, data_attributes)
|
148
|
+
else
|
149
|
+
merge_data_attributes(options, data_attributes)
|
150
|
+
end
|
151
|
+
content_tag(name, content_or_options_with_block, options, escape, &block)
|
152
|
+
end
|
153
|
+
|
124
154
|
def collection_key
|
125
155
|
nil
|
126
156
|
end
|
@@ -129,6 +159,10 @@ module ViewComponentReflex
|
|
129
159
|
initial_param != new_param
|
130
160
|
end
|
131
161
|
|
162
|
+
def omitted_from_state
|
163
|
+
[]
|
164
|
+
end
|
165
|
+
|
132
166
|
def key
|
133
167
|
# initialize session state
|
134
168
|
if !stimulus_reflex? || session[@key].nil?
|
@@ -141,7 +175,7 @@ module ViewComponentReflex
|
|
141
175
|
:@helpers, :@controller, :@request, :@content
|
142
176
|
]
|
143
177
|
instance_variables.reject { |k| blacklist.include?(k) }.each do |k|
|
144
|
-
new_state[k] = instance_variable_get(k)
|
178
|
+
new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
|
145
179
|
end
|
146
180
|
ViewComponentReflex::Engine.state_adapter.store_state(request, @key, new_state)
|
147
181
|
ViewComponentReflex::Engine.state_adapter.store_state(request, "#{@key}_initial", new_state)
|
@@ -155,5 +189,16 @@ module ViewComponentReflex
|
|
155
189
|
end
|
156
190
|
@key
|
157
191
|
end
|
192
|
+
|
193
|
+
private
|
194
|
+
|
195
|
+
def merge_data_attributes(options, attributes)
|
196
|
+
data = options[:data]
|
197
|
+
if data.nil?
|
198
|
+
options[:data] = attributes
|
199
|
+
else
|
200
|
+
options[:data].merge! attributes
|
201
|
+
end
|
202
|
+
end
|
158
203
|
end
|
159
204
|
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
module ViewComponentReflex
|
2
|
-
VERSION = '1.
|
3
|
-
end
|
1
|
+
module ViewComponentReflex
|
2
|
+
VERSION = '1.6.1'
|
3
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_component_reflex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua LeBlanc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|