-
-
Notifications
You must be signed in to change notification settings - Fork 341
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
Add doc for URL binding feature #1346
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2081,6 +2081,8 @@ then render it manually after: | |
|
||
{{ form_widget(form.todoItems.vars.button_add, { label: '+ Add Item', attr: { class: 'btn btn-outline-primary' } }) }} | ||
|
||
.. _validation: | ||
|
||
Validation (without a Form) | ||
--------------------------- | ||
|
||
|
@@ -2302,6 +2304,130 @@ You can also trigger a specific "action" instead of a normal re-render: | |
#} | ||
> | ||
|
||
Changing the URL when a LiveProp changes | ||
---------------------------------------- | ||
|
||
.. versionadded:: 2.14 | ||
|
||
The ``url`` option was introduced in Live Components 2.14. | ||
|
||
If you want the URL to update when a ``LiveProp`` changes, you can do that with the ``url`` option:: | ||
|
||
// src/Components/SearchModule.php | ||
namespace App\Components; | ||
|
||
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; | ||
use Symfony\UX\LiveComponent\Attribute\LiveProp; | ||
use Symfony\UX\LiveComponent\DefaultActionTrait; | ||
|
||
#[AsLiveComponent] | ||
class SearchModule | ||
{ | ||
use DefaultActionTrait; | ||
|
||
#[LiveProp(writable: true, url: true)] | ||
public string $query = ''; | ||
} | ||
|
||
Now, when the user changes the value of the ``query`` prop, a query parameter in the URL will be updated to reflect the | ||
new state of your component, for example: ``https://my.domain/search?query=my+search+string``. | ||
|
||
If you load this URL in your browser, the ``LiveProp`` value will be initialized using the query string | ||
(e.g. ``my search string``). | ||
|
||
.. note:: | ||
|
||
The URL is changed via ``history.replaceState()``. So no new entry is added. | ||
|
||
.. warning:: | ||
|
||
You can use multiple components with URL bindings in the same page, as long as bound field names don't collide. | ||
Otherwise, you will observe unexpected behaviors. | ||
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. Someone may have suggested adding this, I say remove it. I think this is self-evident (e.g. if you have 2 variables defined in the same function with the same name, unexpected things will happen). 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. Do you suggest removing the full warning block or just the last line? |
||
|
||
Supported Data Types | ||
~~~~~~~~~~~~~~~~~~~~ | ||
|
||
You can use scalars, arrays and objects in your URL bindings: | ||
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. You say objects but then don't show an example below. 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. That was the purpose of the last example: |
||
|
||
============================================ ================================================= | ||
JavaScript ``prop`` value URL representation | ||
============================================ ================================================= | ||
``'some search string'`` ``prop=some+search+string`` | ||
``42`` ``prop=42`` | ||
``['foo', 'bar']`` ``prop[0]=foo&prop[1]=bar`` | ||
``{ foo: 'bar', baz: 42 }`` ``prop[foo]=bar&prop[baz]=42`` | ||
|
||
|
||
When a page is loaded with a query parameter that's bound to a ``LiveProp`` (e.g. ``/search?query=my+search+string``), | ||
the value - ``my search string`` - goes through the hydration system before it's set onto the property. If a value can't | ||
be hydrated, it will be ignored. | ||
|
||
Multiple Query Parameter Bindings | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
You can use as many URL bindings as you want in your component. To ensure the state is fully represented in the URL, | ||
all bound props will be set as query parameters, even if their values didn't change. | ||
|
||
For example, if you declare the following bindings:: | ||
|
||
// ... | ||
#[AsLiveComponent] | ||
class SearchModule | ||
{ | ||
#[LiveProp(writable: true, url: true)] | ||
public string $query = ''; | ||
|
||
#[LiveProp(writable: true, url: true)] | ||
public string $mode = 'fulltext'; | ||
|
||
// ... | ||
} | ||
|
||
|
||
And you only set the ``query`` value, then your URL will be updated to | ||
``https://my.domain/search?query=my+query+string&mode=fulltext``. | ||
|
||
Validating the Query Parameter Values | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Like any writable ``LiveProp``, because the user can modify this value, you should consider adding | ||
:ref:`validation <validation>`. When you bind a ``LiveProp`` to the URL, the initial value is not automatically | ||
validated. To validate it, you have to set up a `PostMount hook`_:: | ||
|
||
// ... | ||
use Symfony\Component\Validator\Constraints as Assert; | ||
use Symfony\UX\LiveComponent\ValidatableComponentTrait; | ||
use Symfony\UX\TwigComponent\Attribute\PostMount; | ||
|
||
#[AsLiveComponent] | ||
class SearchModule | ||
{ | ||
use ValidatableComponentTrait; | ||
|
||
#[LiveProp(writable: true, url: true)] | ||
public string $query = ''; | ||
|
||
#[LiveProp(writable: true, url: true)] | ||
#[Assert\NotBlank] | ||
public string $mode = 'fulltext'; | ||
|
||
#[PostMount] | ||
public function postMount(): void | ||
{ | ||
// Validate 'mode' field without throwing an exception, so the component can be mounted anyway and a | ||
// validation error can be shown to the user | ||
if (!$this->validateField('mode', false)) { | ||
// Do something when validation fails | ||
} | ||
} | ||
|
||
// ... | ||
} | ||
|
||
.. note:: | ||
|
||
You can use `validation groups`_ if you want to use specific validation rules only in the PostMount hook. | ||
|
||
.. _emit: | ||
|
||
Communication Between Components: Emitting Events | ||
|
@@ -3315,3 +3441,5 @@ bound to Symfony's BC policy for the moment. | |
.. _`Symfony's built-in form theming techniques`: https://symfony.com/doc/current/form/form_themes.html | ||
.. _`pass content to Twig Components`: https://symfony.com/bundles/ux-twig-component/current/index.html#passing-blocks | ||
.. _`Twig Component debug command`: https://symfony.com/bundles/ux-twig-component/current/index.html#debugging-components | ||
.. _`PostMount hook`: https://symfony.com/bundles/ux-twig-component/current/index.html#postmount-hook | ||
.. _`validation groups`: https://symfony.com/doc/current/form/validation_groups.html |
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.
right?
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.
Other examples in the doc live in
src/Components
, not sure why this one should be different?