Skip to content

Commit f3cbba9

Browse files
Merge pull request #286 from basemate/implementing_issue_75
enable usage of async rerender_on on component-level
2 parents 338104b + deca1da commit f3cbba9

File tree

4 files changed

+147
-22
lines changed

4 files changed

+147
-22
lines changed

app/concepts/matestack/ui/core/component/dynamic.rb

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def components(&block)
157157
@nodes = Matestack::Ui::Core::ComponentNode.build(self, nil, &block)
158158

159159
@nodes.each do |key, node|
160-
@cells[key] = to_cell(key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
160+
@cells[key] = to_cell("#{@component_key}__#{key}", node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
161161
end
162162
end
163163

@@ -190,6 +190,38 @@ def modifiers
190190
result.join(" ")
191191
end
192192

193+
def render_child_component component_key, current_search_keys_array
194+
if respond_to? :prepare
195+
prepare
196+
end
197+
198+
response
199+
200+
if current_search_keys_array.count > 1
201+
if @nodes.dig(*current_search_keys_array) == nil
202+
rest = []
203+
while @nodes.dig(*current_search_keys_array) == nil
204+
rest << current_search_keys_array.pop
205+
end
206+
node = @nodes.dig(*current_search_keys_array)
207+
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
208+
begin
209+
return cell.render_child_component component_key, rest.reverse[1..-1]
210+
rescue
211+
return cell.render_content
212+
end
213+
else
214+
node = @nodes.dig(*current_search_keys_array)
215+
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
216+
return cell.render_content
217+
end
218+
else
219+
node = @nodes[current_search_keys_array[0]]
220+
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
221+
return cell.render_content
222+
end
223+
end
224+
193225
private
194226

195227
def generate_children_cells

app/concepts/matestack/ui/core/page/page.rb

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,23 +91,9 @@ def show(component_key=nil, only_page=false)
9191
concept(@app_class).call(:show, @page_id, @nodes)
9292
when :render_component
9393
begin
94-
if component_key.include?("__")
95-
keys_array = component_key.gsub("__", "__components__").split("__").map {|k| k.to_s}
96-
page_content_keys = keys_array.select{|key| key.match(/^page_content_/)}
97-
if page_content_keys.any?
98-
keys_array = keys_array.drop(keys_array.find_index(page_content_keys[0])+2)
99-
end
100-
node = @nodes.dig(*keys_array)
101-
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
102-
return cell.render_content
103-
else
104-
node = @nodes[component_key]
105-
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
106-
return cell.render_content
107-
end
108-
rescue
109-
raise "Component '#{component_key}' could not be resolved. Notice: Rerendering currently works only on page-level. \
110-
You are therefore currently not able to use 'async' within a component for example!"
94+
render_child_component component_key
95+
rescue => e
96+
raise "Component '#{component_key}' could not be resolved."
11197
end
11298
end
11399
end
@@ -116,6 +102,34 @@ def page_id
116102
@custom_page_id ||= @page_id
117103
end
118104

105+
def render_child_component component_key
106+
if component_key.include?("__")
107+
keys_array = component_key.gsub("__", "__components__").split("__").map {|k| k.to_s}
108+
page_content_keys = keys_array.select{|key| key.match(/^page_content_/)}
109+
if page_content_keys.any?
110+
keys_array = keys_array.drop(keys_array.find_index(page_content_keys[0])+2)
111+
end
112+
if @nodes.dig(*keys_array) == nil
113+
rest = []
114+
while @nodes.dig(*keys_array) == nil
115+
rest << keys_array.pop
116+
end
117+
node = @nodes.dig(*keys_array)
118+
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
119+
return cell.render_child_component component_key, rest.reverse[1..-1]
120+
else
121+
node = @nodes.dig(*keys_array)
122+
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
123+
return cell.render_content
124+
end
125+
else
126+
node = @nodes[component_key]
127+
cell = to_cell(component_key, node["component_name"], node["config"], node["argument"], node["components"], node["included_config"], node["cached_params"])
128+
return cell.render_content
129+
end
130+
end
131+
132+
119133
private
120134

121135
def resolve_isolated_component component_key

docs/components/async.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ As the name suggests, the async component allows us to let our components behave
66

77
Please be aware that, if not configured otherwise, the async core component does get loaded and displayed on initial pageload!
88

9-
**the async component currently only works on page-level --> we're working on it in order support the usage of async within a component [#75](https://github.com/basemate/matestack-ui-core/issues/75)**
10-
119
## Parameters
1210

1311
The async core component accepts the following parameters:

spec/usage/components/async_spec.rb

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
describe "Async Component", type: :feature, js: true do
55

6-
it "Example 1 - Rerender on event" do
6+
it "Example 1 - Rerender on event on page-level" do
77

88
class ExamplePage < Matestack::Ui::Page
99

@@ -32,7 +32,88 @@ def response
3232
expect(before_content).not_to eq(after_content)
3333
end
3434

35-
it "Example 1.1 - Rerender on event if wrapped in app" do
35+
it "Example 1.1 - Rerender on event on (nested) component-level" do
36+
37+
module Components end
38+
module Components::Some end
39+
module Components::Other end
40+
41+
class ExamplePage < Matestack::Ui::Page
42+
43+
def response
44+
components {
45+
div do
46+
custom_some_component
47+
end
48+
}
49+
end
50+
51+
end
52+
53+
class Components::Some::Component < Matestack::Ui::StaticComponent
54+
55+
def response
56+
components {
57+
div id: "static-content-on-component" do
58+
plain "Component 1: #{DateTime.now.strftime('%Q')}"
59+
end
60+
async rerender_on: "my_event" do
61+
div id: "dynamic-content-on-component" do
62+
plain "Component 1: #{DateTime.now.strftime('%Q')}"
63+
end
64+
end
65+
async rerender_on: "my_other_event" do
66+
custom_other_component
67+
div id: "other-dynamic-content-on-component" do
68+
plain "Component 1: #{DateTime.now.strftime('%Q')}"
69+
end
70+
end
71+
}
72+
end
73+
74+
end
75+
76+
class Components::Other::Component < Matestack::Ui::StaticComponent
77+
78+
def response
79+
components {
80+
div id: "static-content-on-other-component" do
81+
plain "Component 2: #{DateTime.now.strftime('%Q')}"
82+
end
83+
async rerender_on: "my_event" do
84+
div id: "dynamic-content-on-other-component" do
85+
plain "Component 2: #{DateTime.now.strftime('%Q')}"
86+
end
87+
end
88+
async rerender_on: "my_other_event" do
89+
div id: "other-dynamic-content-on-other-component" do
90+
plain "Component 2: #{DateTime.now.strftime('%Q')}"
91+
end
92+
end
93+
}
94+
end
95+
96+
end
97+
98+
99+
visit "/example"
100+
101+
static_content_before = page.find("#static-content-on-component").text
102+
dynamic_content_before = page.find("#dynamic-content-on-component").text
103+
other_dynamic_content_before = page.find("#other-dynamic-content-on-component").text
104+
105+
page.execute_script('MatestackUiCore.matestackEventHub.$emit("my_event")')
106+
# sleep
107+
static_content_after = page.find("#static-content-on-component").text
108+
dynamic_content_after = page.find("#dynamic-content-on-component").text
109+
other_dynamic_content_after = page.find("#other-dynamic-content-on-component").text
110+
111+
expect(static_content_before).to eq(static_content_after)
112+
expect(dynamic_content_before).not_to eq(dynamic_content_after)
113+
expect(other_dynamic_content_before).to eq(other_dynamic_content_after)
114+
end
115+
116+
it "Example 1.2 - Rerender on event on page-level if wrapped in app" do
36117

37118
class Apps::ExampleApp < Matestack::Ui::App
38119

0 commit comments

Comments
 (0)