Skip to content

Commit 01412c2

Browse files
committed
feature #500 [LiveComponents] Hello Component JS Object (weaverryan)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [LiveComponents] Hello Component JS Object | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Tickets | Fix None | License | MIT Hi! This is effectively a rewrite of the LiveComponents frontend (with minimal effect on users). It introduces: A) A `Component` object that "mirrors" your PHP component object and lives in a `__component` property of your element - this allows you to do cool things like: ```js const component = document.getElementById('component-id').__component // set the firstName property and re-render // effectively set the firstName property on your PHP object component.firstName = 'Ryan'; // trigger the "save" LiveAction component.save(); ``` B) Logic is much more organized between `live_controller.ts` (mostly event listening & initialization), `Component.ts` (model+action & Ajax handling) and a number of "plugins" that add loading, polling, etc). C) Child handling is more intelligent: child components will NOT re-render when their parent component re-renders, unless the data passed *into* the child has changed. It does this by generating a "fingerprint" (checksum) of the values that are passed *into* a child component when `{{ component() }}` is called. Then, when a parent re-renders, the "fingerprints" if its children are sent with the request. If any of those fingerprints are seen to have changed during the re-render, then we know the "input" to a child has changed and the child should be re-rendered (which is done basically by sending a signal to the child component to re-render itself with a new set of props). D) Child/parent data passing is now done with a `dataModel` prop. TODOs: * [x] 1) Update CHANGELOG * [x] 2) add some sort of `v-model` (previously called `data-model-map`) ability: where a child can communicate a model change to its parent * [X] 3) BACKEND: pass `data` (writable props) & `props` separately as live controller values * [x] 4) BACKEND: pass the a deterministic `data-live-id` attribute to the child unless manually specified * [x] 5) BACKEND: pass a "fingerprint" value to Stimulus (fingerprint is a checksum of the values passed IN when creating a component) * [x] 6) BACKEND: read `childrenFingerprints` data for GET (JSON-encoded query param) and POST (request body). Use this to compare to the NEW fingerprint value for each child. If not changed, render the child as an empty element (with only `data-live-id`). If changed, render an empty element, but with `data-live-id`, the new fingerprint `data-` value *and* the new `data-live-props-value`. * [ ] 7) DOCS: Add at least one new example to ux.symfony.com * [ ] 8) DOCS: add example with data-live-id manually being set on a child so it re-renders under some situation * [ ] 9) Find better example for the custom Stimulus controller that goes around the component in the docs * [ ] 10) (Maybe later) a way for a child component to trigger a re-render on the parent (without a model in the parent needing to change) Cheers! Commits ------- aac55bf Adding a data-model system for sync'ing data between parent and child components fd97102 Fixes various tests 9701450 Resetting deterministic id to avoid numbering problems in different parents 5df34f2 Renaming class that was in a bad directory & new event 4909915 Setting childrenFingerprints from request onto MountedComponent 2ffbd2c fixing outdated internal reference to before rerender 0adcdc3 Adding a fingerprint to child components that is a hash of their "input props" 297e388 Fixing bug where file paths on the system caused id to not be so deterministic ed462f3 Adding ComponentStack to keep track of currently-rendered components and parents fc4883c Split backend to data and props d1076f8 Updating docs for working via JS & making change event always update a model e38381e abstracting last bits of markup out of component 30619de Making several component methods return a Promise 0c56bc6 Removing todo and other things that will be re-worked later 321f2e4 Moving more systems into plugins 45bcaf4 removing data-live-id-value in favor of data-live-id - no need for both 3ccf783 Abstracting more markup-related thing to the new "driver" + plugin system 1394883 Reset models when resetting data from server 07f8517 Work on child rendering tests e5cc4e0 Starting new child tests 6b7fcd2 Sending childrenFingerprints data to server on Ajax call 526e570 Adding the fingerprint to the system, but not using it yet b1ac91c client-side implementation of differentiating between data & props 2a22483 initial component child tracking/setup 32d4ff3 WIP heavy refactoring to Component 9bf843b # This is a combination of 6 commits. # This is the 1st commit message:
2 parents c68def3 + aac55bf commit 01412c2

File tree

112 files changed

+6408
-2959
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+6408
-2959
lines changed

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@
4848
],
4949
"rules": {
5050
"@typescript-eslint/no-explicit-any": "off",
51-
"@typescript-eslint/no-empty-function": "off"
51+
"@typescript-eslint/no-empty-function": "off",
52+
"@typescript-eslint/ban-ts-comment": "off",
53+
"quotes": [
54+
"error",
55+
"single"
56+
]
5257
},
5358
"env": {
5459
"browser": true

src/Cropperjs/Resources/assets/test/controller.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ describe('CropperjsController', () => {
5252
data-cropperjs-public-url-value="https://symfony.com/logos/symfony_black_02.png"
5353
data-cropperjs-options-value="${dataToJsonAttribute({
5454
viewMode: 1,
55-
dragMode: "move"
55+
dragMode: 'move'
5656
})}"
5757
>
5858
</div>

src/LiveComponent/CHANGELOG.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,25 @@
2626
<input data-model="firstName">
2727
```
2828
29-
- Added the ability to add `data-loading` behavior, which is only activated
29+
- [BEHAVIOR CHANGE] The way that child components re-render when a parent re-renders
30+
has changed, but shouldn't be drastically different. Child components will now
31+
avoid re-rendering if no "input" to the component changed _and_ will maintain
32+
any writable `LiveProp` values after the re-render. Also, the re-render happens
33+
in a separate Ajax call after the parent has finished re-rendering.
34+
35+
- [BEHAVIOR CHANGE] If a model is updated, but the new value is equal to the old
36+
one, a re-render will now be avoided.
37+
38+
- [BC BREAK] The `live:update-model` and `live:render` events are not longer
39+
dispatched. You can now use the "hook" system directly on the `Component` object/
40+
41+
- [BC BREAK] The `LiveComponentHydrator::dehydrate()` method now returns a
42+
`DehydratedComponent` object.
43+
44+
- Added a new JavaScript `Component` object, which is attached to the `__component`
45+
property of all root component elements.
46+
47+
- the ability to add `data-loading` behavior, which is only activated
3048
when a specific **action** is triggered - e.g. `<span data-loading="action(save)|show">Loading</span>`.
3149
3250
- Added the ability to add `data-loading` behavior, which is only activated

0 commit comments

Comments
 (0)