Allow to execute CableReady operations on `StimulusReflex::Element`
Type of PR
Feature
Description
As of today we just have one StimulusReflex::Element instance which is available as element in your reflex.
This PR enables to call CableReady operations on any instance of the said StimulusReflex::Element class. Like this we enable a very DOM-like and natural API in a reflex action to operate on those elements.
Additionally it adds another element accessor to the reflex class named controller_element. This is the element in the DOM which holds the Stimulus Controller you are operating on.
This enables scenarios like:
class CounterReflex < StimulusReflex::Reflex
def increment
@count = element.dataset.count.to_i + element.dataset.step.to_i
element.inner_html(html: @count)
element.dispatch_event(name: 'increment', detail: { count: @count })
element.set_focus
controller_element.set_dataset_property(name: "counterValue", value: @count)
morph :nothing
end
end
This PR is part of a bigger story. The PR #490 proposes the introduction of StimulusReflex targets. With that you can declare any DOM node as a StimulusReflex target (like you do in your Stimulus controller). This enables you to then access and operate on the targets in your Reflexes the same way you can with element and controller_element.
Why should this be added
Makes the API even more awesome and straight-forward, it feels like you are operating on an actual DOM Node via the actual DOM API. It also makes the use of CableReady more transparent.
Checklist
- [x] My code follows the style guidelines of this project
- [x] Checks (StandardRB & Prettier-Standard) are passing
Deploy Preview for stimulusreflex ready!
| Name | Link |
|---|---|
| Latest commit | 1f38f9e534a52cbc9fd8238f74950738e4e56cf8 |
| Latest deploy log | https://app.netlify.com/sites/stimulusreflex/deploys/63f41f71c0efa500088047dd |
| Deploy Preview | https://deploy-preview-489--stimulusreflex.netlify.app |
| Preview on mobile | Toggle QR Code...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify site settings.
Wooooah this is wild :heart:
Is element.broadcast getting called implicitly somewhere when the reflex is finished? It's not called explicitly in the example...
element.inner_html(html: @count)
element.dispatch_event(name: 'increment', detail: { count: @count })
element.set_focus
@Matt-Yorkley Yeah, StimulusReflex calls cable_ready.broadcast at the end of every reflex execution. This is also already happening today if you use the cable_ready inside a reflex action.
But since calling element.inner_html(...) just enqueues a regular operation using cable_ready under the hood it's also getting flushed at the same time.
I just gave this a little live-test on top of 3.5.0-rc2 and it almost works perfectly, except the selector attribute on the element is in xpath format and the cable ready operations default to xpath: false.
StimulusReflex::Channel transmitting {"cableReady"=>true, "operations"=>[{"selector"=>"/html/body/section[1]/div[1]/div[2]/button[1]", "xpath"=>false, "text"=>"TEST", "reflexId"=>"b913191f-bf74-49b0-8e07-c15ecae87964", "operation"=>"textContent"}
Looks like it just needs a single slash instead of a double in StimulusReflex::Element#method_missing:
-- xpath = selector ? selector.starts_with?("//") : false
++ xpath = selector ? selector.starts_with?("/") : false
It works!
@Matt-Yorkley this is great news, thanks for giving this a shot!