-
-
Notifications
You must be signed in to change notification settings - Fork 364
[WIP][Live] New data-rerender mode for handling custom JavaScript #519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -475,6 +475,100 @@ The following hooks are available (along with the arguments that are passed): | |||||
* ``loading.state:finished`` args ``(element: HTMLElement)`` | ||||||
* ``model:set`` args ``(model: string, value: any, component: Component)`` | ||||||
|
||||||
Handling Re-Rendering & Custom JavaScript | ||||||
------------------------------------------ | ||||||
|
||||||
A common use-case for live components is to initialize extra JavaScript | ||||||
after the component renders - e.g. to transform a date field into a | ||||||
date picker, open a modal or many other things. This is best done via | ||||||
a Stimulus controller. | ||||||
|
||||||
However, if that JavaScript makes changes to your markup - like adding classes | ||||||
or elements - this will causes a problem: when the component re-renders, it will | ||||||
"replace" those changes with the fresh HTML from the server. Suddenly, your | ||||||
cool date picker widget stops working! | ||||||
|
||||||
To solve this, live components has a smart "re-rendering" mode that you | ||||||
can control via a ``data-rerender`` attribute. | ||||||
|
||||||
``data-rerender="never"`` | ||||||
Never re-render this element: leave it completely alone. | ||||||
|
||||||
``data-rerender="always"`` | ||||||
Always re-render this element. This implies that the ``complete`` | ||||||
mode should be used, which totally replaces the element with a | ||||||
new one. This works will with Stimulus because the ``connect()`` | ||||||
method will be called again. | ||||||
|
||||||
``data-rerender="if(propName)"`` | ||||||
Do a ``complete`` re-render but *only* if the ``propName`` LiveProp | ||||||
changed since the last re-render. This is useful to completely | ||||||
re-render an element (e.g. a date picker) but *only* if the value | ||||||
of the date picker changed (to avoid the date picker JavaScript from | ||||||
needlessly being reinitialized on *every* re-render. To re-render if | ||||||
any of multiple models change, pass all of them: ``if(user.firstName, user.lastName)``. | ||||||
|
||||||
You can also specify "targets" for the re-render: | ||||||
|
||||||
``data-rerender="children"`` | ||||||
Always re-render this element, but *only* the children. Avoid making | ||||||
any changes to the parent element that holds this attribute. This is | ||||||
useful to add to modal wrappers so that, if the modal is open, re-rendering | ||||||
won't override the classes that caused it to display as open. Note: ``children`` | ||||||
are always re-rendered using the normal, "diff" mode. | ||||||
|
||||||
``data-rerender="self|if(someProp)"`` | ||||||
Only re-render the parent element that holds this attribute and only | ||||||
if the ``someProp`` LiveProp changed. This could be useful if you're | ||||||
rendering a chart | ||||||
|
||||||
You can even specify multiple directives separated by a space: | ||||||
``data-rerender="children|if(someProp) self|always"``. | ||||||
|
||||||
.. note:: | ||||||
|
||||||
Want to get geeky & technical? The full, format of | ||||||
``data-rerender`` is: ``{target}|{mode}|{when}``: | ||||||
|
||||||
- ``target`` includes ``self``, ``children``, ``all`` (default) | ||||||
- ``mode`` includes ``diff`` & ``complete`` (default). ``diff`` is the | ||||||
default mode used by live components where the new element is | ||||||
"morphed" onto the existing element by applying a diff of changes. However, | ||||||
as soon as you specify ``data-render``, ``complete`` becomes the default | ||||||
if not specified. | ||||||
- ``when`` (*required*) includes ``never``, ``always``, ``if`` | ||||||
|
||||||
If only one target (e.g. ``self``) is included in the ``data-rerender``, then | ||||||
it's assumed that the other target (e.g. ``children``) should never be | ||||||
re-rendered. In other words, using ``self|always`` implies also ``children|never``. | ||||||
|
||||||
TODO: add examples | ||||||
|
||||||
A) Datepicker | ||||||
B) Modal | ||||||
C) Chart that animates on change (with & without UX chart.js?) | ||||||
|
||||||
TODO: deprecate or at least move ``data-live-ignore`` docs up here | ||||||
|
||||||
JavaScript: Date Picker Example | ||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|
||||||
Suppose you have a ``date-picker`` custom Stimulus controller that | ||||||
some fancy date picker, like ``flatpickr``. To avoid removing the | ||||||
date picker markup on re-render, we want to | ||||||
|
||||||
.. code-block:: twig | ||||||
|
||||||
<div data-render""> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
<input | ||||||
type="date" | ||||||
data-model="startDate" | ||||||
data-controller="date-picker" | ||||||
> | ||||||
</div> | ||||||
|
||||||
TODO: finish & also show with form component | ||||||
|
||||||
Loading States | ||||||
-------------- | ||||||
|
||||||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.