Skip to content

Latest commit

 

History

History
545 lines (409 loc) · 19.2 KB

CHANGELOG.md

File metadata and controls

545 lines (409 loc) · 19.2 KB

CHANGELOG

2.23.0

  • Allow configuring the secret used to compute fingerprints and checksums.

2.22.0

  • Remove CSRF tokens - rely on same-origin/CORS instead

2.19.0

  • Add submitForm() to TestLiveComponent.
  • Add live_action Twig function

2.18.0

  • Add parameter to TestLiveComponent::call() to add files to the request

2.17.0

  • Add modifier option in LiveProp so options can be modified at runtime.
  • Fix collections hydration with serializer in LiveComponents
  • Add loading attribute to defer the rendering on the component after the page is rendered, either when the page loads (loading="defer") or when the component becomes visible in the viewport (loading="lazy").
  • Deprecate the defer attribute.
  • Add UrlMapping configuration object for URL bindings in LiveComponents

2.16.0

  • LiveComponents is now stable and no longer experimental 🥳

  • [BC BREAK] The data-action-name attribute behavior was removed in favor of using Stimulus "action parameters" and data-live-action-param. This is a breaking change if you were using the data-action-name attribute directly in your templates. #1418

    To upgrade your application, follow these changes:

    <button
        data-action="live#action"
    -    data-action-name="debounce(300)|save"
    +    data-live-action-param="debounce(300)|save"
    >Save</button>

    To pass arguments to an action, also use the Stimulus "action parameters" syntax:

    <button
        data-action="live#action"
    -     data-action-name="addItem(id={{ item.id }}, itemName=CustomItem)"
    +     data-live-action-param="addItem"
    +     data-live-id-param="{{ item.id }}"
    +     data-live-item-name-param="CustomItem"
    >Add Item</button>

    Additionally, the prevent modifier (e.g. prevent|save) was removed. Replace this with the standard Stimulus :prevent action option:

    <button
    -    data-action="live#action
    +    data-action="live#action:prevent"
    -    data-action-name="prevent|save"
    +    data-live-action-param="save"
     >Save</button>
  • [BC BREAK] The data-event attribute was removed in favor of using Stimulus "action parameters": rename data-event to data-live-event-param. Additionally, if you were passing arguments to the event name, use action parameter attributes for those as well - e.g. data-live-foo-param="bar". #1418

  • Reverted setting ignoreActiveValue: true in Idiomorph #1548

  • New placeholder macro to generate defer/lazy skeleton #1532

  • improve TestLiveComponent::actingAs() #1461

  • Drop Twig 2 support #1436

  • Add better error message when hydrating dates #1431

  • Store TemplateMap in build_dir #1525

2.15.0

  • [BC BREAK] The data-live-id attribute was changed to id #1484
  • Fixed child handling bug during re-rendering introduced with the new morphing library in 2.14.0 #1484
  • Fix bug where the active input would maintain its value, but lose its cursor position #1501
  • Restrict Twig 3.9 for now #1486

2.14.1

  • Fixed a regression in the testing tools related to the default HTTP method change

2.14.0

  • [BC BREAK] DOM morphing changed from morphdom to idiomorph. As this is a different morphing library, there may be some edge cases where the morphing behavior is different.
  • Add support for URL binding in LiveProp
  • Allow multiple LiveListener attributes on a single method
  • Requests to LiveComponent are sent as POST by default
  • Add method prop to AsLiveComponent to still allow GET requests, usage: #[AsLiveComponent(method: 'get')]
  • Add a new urlReferenceType parameter to AsLiveComponent, which allows to generate different type URL (e.g. absolute) for the component Ajax calls
  • The symfony/serializer dependency is now optional
  • Added a data-skip-morph attribute to allow skipping morphing of an element (the element's attributes will be morphed, but its inner HTML will be overwritten instead of morphed)
  • Added an entry to the packages' package.json file so that @symfony/ux-live-component will appear in the user's importmap.php file if using AssetMapper. This will allow using the JavaScript from the package without extra setup.
  • Fixed edge-case rendering bug where a 2nd Ajax request might start before the 1st finished processing
  • Fix usage of {% embed %} with {% block %} in <twig:> components
  • Fixed data-loading not working when on root element of a component
  • Fixed error when class attributes contained a space at start or end
  • Fixed loading directives being matched in a child component

2.13.2

  • Revert "Change JavaScript package to type: module"

2.13.0

  • Add deferred/lazy rendering of Live Components.
  • Fix option tag synchronization.
  • Handle array-like objects when working with checkboxes.
  • Add Symfony 7 support.
  • Normalize "true" & "false" model values
  • Fix DTO hydration from phpdoc typehints.
  • Fix instantiating LiveComponentMetadata multiple times.
  • Change JavaScript package to type: module.
  • Throwing an error when setting an invalid model name.

2.12.0

  • Add support for (de)hydrating DTO classes in LiveProp.
  • Fixed emit() method of TestLiveComponent to properly test events.
  • Add actionAs() to TestLiveComponent.
  • Fixed rendering bug when using Chrome's translation feature.
  • Add onUpdated() hook for LiveProp.
  • Fix support for Alpine.js & live components.

2.11.0

  • Add helper for testing live components.
  • Add initial file upload support.
  • Respect data-turbo="false" when handling redirects.
  • Fix checksum calculation for deeply nested data.

2.9.0

  • Add support for symfony/asset-mapper

2.8.1

  • Increased the priority of LiveComponentSubscriber ControllerEvent from 0 to 10 to fix incompatibility with SensioFrameworkExtraBundle.

2.8.0

  • [BC BREAK]: The exposed option was changed to writable in LiveProp:
-#[LiveProp(exposed: ['email', 'plainPassword'])]
+#[LiveProp(writable: ['email', 'plainPassword'])]
public User $user;
  • [BC BREAK]: LiveProp values are no longer automatically (de)hydrated through Symfony's serializer. Use LiveProp(useSerializerForHydration: true) to activate this. Also, a serializationContext option was added to LiveProp.

  • [BC BREAK]: Child components are no longer automatically re-rendered when a parent component re-renders and the value of one of the props passed to the child has changed. Pass acceptUpdatesFromParent: true to any LiveProp on the child component to re-enable this behavior.

  • Non-persisted entity objects can now be used with LiveProp: it will be serialized using the serializer.

  • Better support for using arrays with LiveProp.

  • Smart rendering system! If you have JavaScript that makes changes to the DOM inside a live component, those changes will now be kept when the component is re-rendered. This has limitations - see the documentation.

  • You can now emit() events to communicate between components.

  • You can now dispatch DOM/browser events from components.

  • Boolean checkboxes are now supported. Of a checkbox does not have a value attribute, then the associated LiveProp will be set to a boolean when the input is checked/unchecked.

  • A format option was added to LiveProp to control how DateTime properties are (de)hydrated.

  • Added support for setting writable to a property that is an object (previously, only scalar values were supported). The object is passed through the serializer.

  • Invalid data sent by the user is now handled in a robust way. Previously, if the user sent invalid data (e.g. a string for a LiveProp that has an int type), the component update would break. Now, if the new data cannot be hydrated onto the object during a re-render, the last valid value is used.

  • When using ValidatableComponentTrait, a new _errors variable is sent to the template, which is easier to use!

  • Several bug fixes to parent - child components - see #700.

  • Fixed handling of boolean attributes to a component - see #710.

  • Fixed performance calculating component fingerprint for large components.

2.7.0

  • [BC BREAK]: The "key" used to load the controller in your assets/controllers.json file changed from typed to live. Update your assets/controllers.json file to change this key.

  • Add a strategy for adding a Stimulus controller to a Twig component - #589.

  • Added a new getCompontent() function in JavaScript as the best way to find a Component object for a given element.

  • Fixed various bugs related to child component handling - #596

  • Added a new route parameter to AsLiveComponent, which allows to choose another route for Ajax calls.

  • Add assets/src to .gitattributes to exclude source TypeScript files from installing.

  • TypeScript types are now included.

  • Added new response:error JavaScript component hook for custom handling Ajax errors - #587.

2.6.0

  • [BC BREAK]: The path to live_component.xml changed and the import now MUST have a prefix: you should update your route import accordingly (the name of the route also changed to ux_live_component):
# config/routes/ux_live_component.yaml
live_component:
-    resource: '@LiveComponentBundle/Resources/config/routing/live_component.xml'
+    resource: '@LiveComponentBundle/config/routes.php'
+    prefix: /_components
  • Removed Content-Type header when returning the empty response redirect.
  • Fixed bug when re-rendering SVG's (.#557)

2.5.0

  • [BEHAVIOR CHANGE] Previously, Ajax calls could happen in parallel (if you changed a model then triggered an action before the model update Ajax call finished, the action Ajax call would being in parallel). Now, if an Ajax call is currently happening, any future requests will wait until it finishes. Then, all queued changes (potentially multiple model updates or actions) will be sent all at once on the next request.

  • [BEHAVIOR CHANGE] Fields with data-model will now have their value set automatically when the component initially loads and re-renders. For example, previously you needed to manually set the value in your component template:

    <!-- BEFORE -->
    <input data-model="firstName" value="{{ firstName }}">

    This is no longer necessary: Live Components will now set the value on load, which allows you to simply have the following in your template:

    <!-- AFTER -->
    <input data-model="firstName">
  • [BEHAVIOR CHANGE] The way that child components re-render when a parent re-renders has changed, but shouldn't be drastically different. Child components will now avoid re-rendering if no "input" to the component changed and will maintain any writable LiveProp values after the re-render. Also, the re-render happens in a separate Ajax call after the parent has finished re-rendering.

  • [BEHAVIOR CHANGE] If a model is updated, but the new value is equal to the old one, a re-render will now be avoided.

  • [BEHAVIOR CHANGE] Priority of DoctrineObjectNormalizer changed from 100 to -100 so that any custom normalizers are used before trying DoctrineObjectNormalizer.

  • [BC BREAK] The live:update-model and live:render events are not longer dispatched. You can now use the "hook" system directly on the Component object/

  • [BC BREAK] The LiveComponentHydrator::dehydrate() method now returns a DehydratedComponent object.

  • Added a new JavaScript Component object, which is attached to the __component property of all root component elements.

  • the ability to add data-loading behavior, which is only activated when a specific action is triggered - e.g. <span data-loading="action(save)|show">Loading</span>.

  • Added the ability to add data-loading behavior, which is only activated when a specific model has been updated - e.g. <span data-loading="model(firstName)|show">Loading</span>.

  • Unexpected Ajax errors are now displayed in a modal to ease debugging! #467.

  • Fixed bug where sometimes a live component was broken after hitting "Back: in your browser - #436.

2.4.0

  • [BC BREAK] Previously, the id attribute was used with morphdom as the "node id" when updating the DOM after a render. This has changed to data-live-id. This is useful when maintaining the correct order of a list of elements.

  • [BC BREAK] If using LiveCollectionType, the name of the remove field changed from button_delete_prototype to button_delete and the add field changed from button_add_prototype to button_add. Additionally, the allow_add and allow_delete default values were changed from false to true.

  • [BEHAVIOR CHANGE] If an action Ajax call is still processing and a model update occurs, the component will no longer re-render. The model will be updated internally, but not re-rendered (so, any model updates would effectively have the |norender modifier). See #419.

2.3.0

  • [BC BREAK] The data-action="live#update" attribute must now be removed from nearly all elements. This is because LiveComponents now automatically listens to the input event on all elements with a data-model attribute and updates the data. If you previously used data-action="change->live#update" to list on the change event, now you should use the on(change) modifier inside data-model.
<!-- BEFORE -->
<input
    data-model="max"
    data-action="change->live#update"
>

<!-- AFTER -->
<input
    data-model="on(change)|max"
>
  • [BC BREAK] The live#updateDefer action was removed entirely. Now, to update a model without triggering a re-render, use the norender modifier for data-model:
<!-- BEFORE -->
<input
    data-model="max"
    data-action="live#updateDefer"
>

<!-- AFTER -->
<input
    data-model="norender|max"
>
  • [BC BREAK] The name attribute is no longer automatically used to update a model when a parent component has data-action="change->live#update". To make a form's fields behave like "model" fields (but using the name attribute instead of data-model) you need to add a data-model attribute to the <form> element around your fields (NOTE: the new attribute is automatically added to your form element when using ComponentWithFormTrait):
<!-- BEFORE -->
<form data-action="change->live#update">
    <input
        name="max"
    >
</form>

<!-- AFTER -->
<form data-model="on(change)|*">
    <input
        name="max"
    >
</form>

2.2.0

  • The bundle now properly exposes a live controller, which can be imported via your assets/controllers.json file (like any other UX package). Previously, the controller needed to be imported and registered with Stimulus directly (usually in your assets/bootstrap.js file). That is no longer needed.

  • Add a generic LiveCollectionType and LiveCollectionTrait

  • Allow to disable CSRF per component

2.1.0

  • Your component's live "data" is now send over Ajax as a JSON string. Previously data was sent as pure query parameters or as pure POST data. However, this made it impossible to keep certain data types, like distinguishing between null and ''. This has no impact on end-users.

  • Added data-live-ignore attribute. If included in an element, that element will not be updated on re-render.

  • ComponentWithFormTrait no longer has a setForm() method. But there is also no need to call it anymore. To pass an already-built form to your component, pass it as a form var to component(). If you have a custom mount(), you no longer need to call setForm() or anything else.

  • The Live Component AJAX endpoints now return HTML in all situations instead of JSON.

  • Ability to send live action arguments to backend

  • [BC BREAK] Remove init_live_component() twig function, use {{ attributes }} instead:

    - <div {{ init_live_component() }}>
    + <div {{ attributes }}>
  • [BC BREAK] Replace property hydration system with symfony/serializer normalizers. This is a BC break if you've created custom hydrators. They'll need to be converted to normalizers.

  • [BC BREAK] Rename BeforeReRender attribute to PreReRender.

2.0.0

  • Support for stimulus version 2 was removed and support for @hotwired/stimulus version 3 was added. See the @symfony/stimulus-bridge CHANGELOG for more details.

  • Require live components have a default action (__invoke() by default) to enable controller annotations/attributes (ie @Security/@Cache). Added DefaultActionTrait helper.

  • When a model is updated, a new live:update-model event is dispatched. Parent components (in a parent-child component setup) listen to this and automatically try to update any model with a matching name. A data-model-map was also added to map child component model names to a parent - see #113.

  • Child components are now re-rendered if the parent components passes new data to the child when rendering - see #113.

  • Minimum PHP version was bumped to 8.0 so that PHP 8 attributes could be used.

  • The LiveComponentInterface was dropped and replaced by the AsLiveComponent attribute, which extends the new AsTwigComponent from the TwigComponent library. All other annotations (e.g. @LiveProp and @LiveAction) were also replaced by PHP 8 attributes.

Before:

use App\Entity\Notification;
use App\Repository\NotificationRepository;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\LiveComponentInterface;

final class NotificationComponent implements LiveComponentInterface
{
    private NotificationRepository $repo;

    /** @LiveProp */
    public bool $expanded = false;

    public function __construct(NotificationRepository $repo)
    {
        $this->repo = $repo;
    }

    /** @LiveAction */
    public function toggle(): void
    {
        $this->expanded = !$this->expanded;
    }

    public function getNotifications(): array
    {
        return $this->repo->findAll();
    }

    public static function getComponentName(): string
    {
        return 'notification';
    }
}

After:

use App\Entity\Notification;
use App\Repository\NotificationRepository;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveProp;

#[AsLiveComponent('notification')]
final class NotificationComponent
{
    private NotificationRepository $repo;

    #[LiveProp]
    public bool $expanded = false;

    public function __construct(NotificationRepository $repo)
    {
        $this->repo = $repo;
    }

    #[LiveAction]
    public function toggle(): void
    {
        $this->expanded = !$this->expanded;
    }

    public function getNotifications(): array
    {
        return $this->repo->findAll();
    }
}

Pre-Release

  • The LiveComponent library was introduced!