Skip to content

[LiveComponent] Bugfix #1509 - Adjust sequence of operations in the resetForm function #1683

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

Open
wants to merge 7 commits into
base: 2.x
Choose a base branch
from

Conversation

jpvdw86
Copy link

@jpvdw86 jpvdw86 commented Apr 4, 2024

Q A
Bug fix? yes
New feature? no
Issues Fix #1509
License MIT

I have adjusted the sequence of operations in the resetForm function. Previously, the variable "formView" was set to null first, followed by its reassignment using $this->getFormView(). This resulted in the form not being fully reset.

This caused issues with bulk requests. The second request of submitForm expects the form to be reset and $this->formView to be null. By rearranging the operations, I ensured that the form is properly reset before any subsequent operations like bulk requests

Update LogicException
Prevent reinitializes $this->formView variable, after set to null
@carsonbot carsonbot added the Status: Needs Review Needs to be reviewed label Apr 4, 2024
@jpvdw86 jpvdw86 changed the title Bugfix #1509 - Adjust sequence of operations in the resetForm function [Live] Bugfix #1509 - Adjust sequence of operations in the resetForm function Apr 4, 2024
@smnandre
Copy link
Member

smnandre commented Apr 5, 2024

Hey @jpvdw86 thanks for the PR !

Could you maybe add a test or two ?

@@ -137,16 +137,16 @@ public function getFormName(): string
private function resetForm(): void
{
// prevent the system from trying to submit this reset form
$this->formValues = $this->extractFormValues($this->getFormView());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you did not reset form view... form values are the existing ones, and no the new view one.. This seem to change things, no ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states

After submitting a form via an action, you might want to "reset" the form back to its initial state so you can use it again.

With your modification it seems to me this is not the case anymore.. or did I miss something ?

https://symfony.com/bundles/ux-live-component/current/index.html#resetting-the-form

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states

After submitting a form via an action, you might want to "reset" the form back to its initial state so you can use it again.

With your modification it seems to me this is not the case anymore.. or did I miss something ?

https://symfony.com/bundles/ux-live-component/current/index.html#resetting-the-form

Using resetForm is still required. However, prior to this adjustment, not everything was reset. Initially, the value is set to null and filled again two lines later. Therefore, resetting was ineffective. I just change the order in the reset function to ensures that it is truly reset and the values $this->form and $this->formView are null after resetting the form.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What i mean is that this->formValues is no more resetted to its initial mounted values .. or did i miss something ?

}

private function submitForm(bool $validateAll = true): void
{
if (null !== $this->formView) {
throw new \LogicException('The submitForm() method is being called, but the FormView has already been built. Are you calling $this->getForm() - which creates the FormView - before submitting the form?');
throw new \LogicException('The submitForm() method is being called, but the FormView has already been built. Are you calling $this->getForm() - which creates the FormView - before submitting the form? Or did you forget to call $this->resetForm() to reset the form state to support bulk requests?');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you create a small reproducer with bulk requests ? What i'm not sure to get is how bulk requests would interfer .. the component beeing non shared services, they should not receive multiple request, no ?

Copy link
Contributor

@WebMamba WebMamba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Humm there are something I don't understant! The bulk request are made on the javascript side. So when we bulk, Symfony handle different request, so the container is a new container, and so the form are reseted to? am I missing something?

@smnandre
Copy link
Member

Humm there are something I don't understant! The bulk request are made on the javascript side. So when we bulk, Symfony handle different request, so the container is a new container, and so the form are reseted to? am I missing something?

There is a batchactioncontroller in livecomponent... but i did search in the docs and found nothing about it 🤷‍♂️

@jpvdw86
Copy link
Author

jpvdw86 commented Apr 19, 2024

Humm there are something I don't understant! The bulk request are made on the javascript side. So when we bulk, Symfony handle different request, so the container is a new container, and so the form are reseted to? am I missing something?


In livecomponents, there is a function that liveactions request are bundled together in a so-called batch request. This reduces the number of requests to the backend.

However, this results that only one HTTP request is send to the backend en to the batchController. The request is then placed into subkernel requests. Because these are not entirely new requests, they are handled within the same container instance, leading to some issues.

Upon further consideration, I realize that my suggested fix is not the real solution and that more attention should be paid to this functionality, perhaps exploring the option of being able to disable the batch request functionality.

BatchController:

public function __invoke(Request $request, MountedComponent $_mounted_component, string $serviceId, array $actions): ?Response
    {
        foreach ($actions as $action) {
            $name = $action['name'] ?? throw new BadRequestHttpException('Invalid JSON');

            $subRequest = $request->duplicate(attributes: [
                '_controller' => [$serviceId, $name],
                '_component_action_args' => $action['args'] ?? [],
                '_mounted_component' => $_mounted_component,
                '_live_component' => $serviceId,
            ]);

            $response = $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);

            if ($response->isRedirection()) {
                return $response;
            }
        }

        return null;
    }

Jean-Paul and others added 4 commits April 20, 2024 00:04
Modify the behavior of generating a '_batch' request. If an action with the same name already exists in the pending requests, update the previous one. This prevents unnecessary actions and prevent _bulk request when not needed.
@jpvdw86
Copy link
Author

jpvdw86 commented Apr 19, 2024

@smnandre @WebMamba
I reverted my previous code and have now made adjustments to the live controller JavaScript.

The problem occurs when the same action is executed, as all instances of it are added as action to pendingActions. However, when executing the same live action, only the last one is needed since it contains the most recent information.

With this adjustment, it checks if there is already an existing pending action. In that case, the existing one is updated instead of adding a new one.

This prevents unnecessary batch requests and resolves also the issue with the form.

@smnandre
Copy link
Member

I don't see your updates now... only the yarn.lock seems to have been modified (compared to the base 2.x branch) ?

@jpvdw86
Copy link
Author

jpvdw86 commented Apr 20, 2024

I don't see your updates now... only the yarn.lock seems to have been modified (compared to the base 2.x branch) ?

There where reverted. Now my change is available

jpvdw86 and others added 2 commits April 20, 2024 14:29
…th the same name already exists in the pending requests, update the previous one. This prevents unnecessary actions and prevent _bulk request when not needed.
@barbieswimcrew
Copy link
Contributor

Hey guys, I have the same problem... will this fix be merged one day? ❤️

@Kocal
Copy link
Member

Kocal commented Jan 5, 2025

Status: Needs work

The PR needs to be rebased, conflicts to be resolved, tests are missing and yarn.lock changes must be reverted.

Thank you 🙏🏻

@carsonbot carsonbot added Status: Needs Work Additional work is needed and removed Status: Needs Review Needs to be reviewed labels Jan 5, 2025
@Kocal Kocal changed the title [Live] Bugfix #1509 - Adjust sequence of operations in the resetForm function [LiveComponent] Bugfix #1509 - Adjust sequence of operations in the resetForm function Jan 17, 2025
@smnandre
Copy link
Member

smnandre commented Feb 6, 2025

i've extracted one bit of your work to open a smaller PR with --afaik-- no side effects.

#2553

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LiveComponent Status: Needs Work Additional work is needed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[LiveComponent] Batch request to save function, throws error: The submitForm() method is being called, but the FormView has already been built
6 participants