-
-
Notifications
You must be signed in to change notification settings - Fork 348
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
[LiveComponent] How do I manually add a FormError to the Form when my submit-function fails? #1981
Comments
Sorry I don't get what you are trying to do here... What error are you trying to catch ? Form errors happen when the value submitted by the user are not valid but no errors are throw the errors are just added to the form. If the error came from outside the form it's a good idea to have an another props for the error outside the form. |
The Idea is that apart from FormErrors being added by Constraints, FormErrors would also be added manually by the Component. For example, a User submits some data and this data - if valid from a constraint perspective - is then sent to a third party which validates it against some internal constraints and saves it. If this third party rejects the data, or an error occurs in transit, or while saving it, I would like the Form to reflect that by manually adding a FormError. To expand on the example above: #[LiveAction]
public function save(): ?Response
{
/** @var SomeModel $model */
$model = $this->getForm()->getData();
try {
$this->someService->save($model);
} catch (\Throwable $e) {
// Possible error cases would be:
// An error occurred during transit
// Third party server is not available
// manually add an error to the form which would then be rendered by the
// "form_errors(form)" twig function
$error = new FormError('An error occurred while saving your data');
$this->form->addError($error);
}
} If this is currently not possible is it worth thinking about opening a feature request? Otherwise, the FormInterface::addError() function would be obsolete within LiveComponents. |
Ok now I got it now, thanks! You can't add Errors after your form have been submitted and validated. This not about LiveComponent, but more about how Symfony form works. So I think you have two options:
|
Yea I thought about these too, however they would still feel like a workaround, because even when adding the FormError to the form within the "instantiateForm()" function it is not rendered - and at this point the form is not submitted. |
Only errors related to validated field / models are kept (see: https://github.com/symfony/ux-live-component/blob/2.x/src/ComponentWithFormTrait.php), and the live props are the form values, not the form itself. Not sure at all, but maybe you can call resetForm and then add some error ? |
I’m struggling with the same issue. @smnandre @WebMamba TestController.php <?php
declare(strict_types=1);
namespace App\Security\Infrastructure\Ui\Http\Registration;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
#[Route(
path: '/test',
methods: [
Request::METHOD_GET,
Request::METHOD_POST,
]
)]
class TestController extends AbstractController
{
public function __invoke(Request $request): Response
{
$form = $this->createFormBuilder()
->add('name', TextType::class)
->add('submit', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$form->get('name')->addError(new FormError('some custom error'));
}
return $this->render(
view: 'test.html.twig',
parameters: [
'form' => $form->createView(),
],
);
}
} test.html.twig {% block content %}
{{ form_start(form) }}
{{ form_end(form) }}
{% endblock %} ![]() It’s clear that the name field has no validation applied; instead, a FormError is manually added to the field, and the error message appears below the input field. |
So you probably need to do something a bit dirthy with https://github.com/symfony/ux-live-component/blob/2.x/src/ValidatableComponentTrait.php |
@smnandre The ValidatableComponentTrait looks like it can only be used for validating constraints on demand which is nice to have, however the errors I would like to display are somewhat independent of the underlying model and its constraints. While that may sound like a case of "well then display the errors independently of the form", they still kind of belong within the form context and being able to utilize the Maybe this example showcases the problem a bit better: #[LiveAction]
public function save(): ?Response
{
try {
/// ... send data to third party server that may raise its own validation error
} catch (ThirdPartyServerValidationError $e) {
$error = new FormError('An external validation error occurred');
$this->getForm()->addError($error);
throw UnprocessableEntityHttpException();
}
} Is there a reason why only FormErrors corresponding to a validatedField entry are displayed? Is it possible to make the validatedFields be co-dependent on existing FormErrors on Form instantiation/rendering? |
This is why i suggested some diving deep in the Trait if you want to make it work as you wish ... and maybe why not open a PR afterward ? |
Behold! My first pull request ... |
Let me preface by saying "yea I know this aint probably the right place to ask", but I am fairly certain this problem is unwanted behaviour...but I'd be glad to be proven wrong.
The LiveComponent would be pretty simple:
The template, as simple as can be:
A somewhat ugly workaround would be adding a $formErrors array property to the component and populating it with whatever error-messages occur. You could then simply display all those messages in the template, though due to how detached that is from the normal symfony form workflow I would rather avoid this.
I understand that throwing a UnprocessableEntityHttpException() makes turbo re-render the HTML it receives in the response, so the "save()" function should throw that whenever it fails. But the errors are not added to the response HTML anyway - either because the HTML has already been rendered or the FormErrors are removed manually...though I have no idea
I tried adding a writable LiveProp array property to my component which would be populated with FormErrors throughout the submit process - similar to the hacky $formErrors array property mentioned above. But the "instantiateForm()" function would add these errors manually to the form - but that does not work either.
Any pointers would be helpful.
The text was updated successfully, but these errors were encountered: