Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Form] Add ability to clear form errors#27580
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
ff852b9 to10985d3Compare| * | ||
| * @return $this | ||
| */ | ||
| publicfunctionclearErrors($deep =false); |
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.
Couldtrue be a better default here? How frequent is to clear errors for root form only? I think most of the time it happens inside a child field.
There is an issue about the same default butgetErrors($deep = false) method#25738 and was reported as confusing.
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.
I don't have a strong preference either way, but I do think the default value here should matchgetErrors().
TerjeBr commentedJun 12, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I have now thought about this, what about adding a |
| // Clear errors from children | ||
| foreach ($thisas$child) { | ||
| if ($childinstanceof ClearableErrorInterface) { | ||
| $child->clearErrors(true); |
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.
Is it possible to have a clearable form type nested in a non-clearable one?
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.
Yes, buttons are not clearable and they could be included in a form that is clearable.
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.
The question was the other way round. As the code here stops the traversal of the form tree as soon as a non-clearable form type is encountered, it will not clear clearable fields nested in non-clearable ones.
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.
The only non-clearable fields we have in the symfony core are buttons that can't have children.
This could append in libraries but then it can be considered the responsibility of the library to implement this interface if needed.
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.
Yeah, I know. But why risk it, if the change would be fairly easy?
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.
It would mean children won't be able to implement custom error cleaning logic, that's something someone might want to do.
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.
Yeah, I know. But why risk it, if the change would be fairly easy?
We can't addclearErrors() toFormInterface as that would be a BC break. And even if we could, that would require us to implementclearErrors() on theButton class, which makes no sense because buttons can't have errors or children - it'll either be a pointless no-op or throw aBadMethodCallException.
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.
I wasn't hinting at implementing it everywhere, but decoupling the traversal of the form tree from the actual form field clearing.
Like the visitor pattern, if you will.
But this edge case doesn't seem too severe.
| * | ||
| * @return $this | ||
| */ | ||
| publicfunctionclearErrors($deep =false); |
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.
Let's add type hint to argumentpublic function clearErrors(bool $deep = false);.
But please don't add: self, we already had discussion on this (#27190 (comment)).
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.
Added and amended! Thanks for the feedback 👍
f365b92 tof86e407Comparevudaltsov commentedJun 14, 2018
If the method is |
f86e407 to17c427eComparecolinodell commentedJun 14, 2018
Good idea@vudaltsov, I like that better! I have made that change. |
vudaltsov left a comment
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.
Awesome! Looking forward to AJAX partial form reloading without errors workarounds 😃
HeahDude left a comment
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.
Looks good, thanks!
| * | ||
| * @return $this | ||
| */ | ||
| publicfunctionclearErrors(bool$deep =false); |
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.
You should type hint: self here
vudaltsovJun 16, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
@HeahDude , we had a discussion on return types here:#27190 (comment)
The problem will be that when using->clearErrors()-> on actual object implementing this interface, the IDE will not show any other methods in autocomplete, because: self is not: static. So from my opinion it's much better to leave@return $this phpdoc.
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.
You can leave the@return $this phpdoc and add: self at the same time. AFAIK phpdoc takes precedence with type declaration for IDE auto completion, this means we would get both the correct auto completion and strictness at the language level (that an instance of the interface is returned).
vudaltsovJun 16, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
okay, then let's use: self 😄
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.
Using: self on an interface forces theForm subclass implementation to use a: ClearableErrorsInterace typehint:
Fatal error: Declaration of Symfony\Component\Form\Form::clearErrors(bool $deep = false): Symfony\Component\Form\Form must be compatible with Symfony\Component\Form\ClearableErrorsInterface::clearErrors(bool $deep = false): Symfony\Component\Form\ClearableErrorsInterface in src/Symfony/Component/Form/Form.php on line 61I'm not sure this is what we want.
AFAIK phpdoc takes precedence with type declaration for IDE auto completion
I could not get this working in the latest version of PhpStorm:
Furthermore, I could not find any other interfaces in Symfony with a: self return type hint. For these reasons I think we should leave it as-is.
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.
The fact that we don't have any existing interfaces with aself return type hint is probably because we couldn't make use of them before Symfony 4. So I would still use it here and use the docblock to be more precise.
| /** | ||
| * Removes all the errors of this form. | ||
| * | ||
| * @param bool $deep whether to remove errors from child forms as well |
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.
Symfony code base uses capital style to comment params.
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.
Fixed, amended, and force-pushed :) Thanks for catching that!
17c427e to5c1a657Comparesrc/Symfony/Component/Form/Form.php Outdated
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| publicfunctionclearErrors(bool$deep =false) |
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.
missing return type hint (same in the interface)
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.
actually I am not even sure if it makes sense that this method returns anything
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.
All form methods are chainable, so it makes sense to keep it here.
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.
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.
I think it's time to decide this once and for all inhttps://symfony.com/doc/current/contributing/code/standards.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.
Well, fluent methods are a pain for return types. so even if we want to have as much return types as possible for new APIs, I'm not sure we want them for fluent APIs.
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.
@xabbuh@stof I have removedreturn $this; from the method for a few reasons:
- You're right, this method doesn't really need to be chainable.
- ClearableTokenStorageInterface (a new and similar interface introduced in SF4) does not return anything, so perhaps we should be consistent here.
- It seems like there's no definitive rule on how to type hint interface methods that return
$this/self. I don't want to set a bad precedent here.
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.
Then you should add: void in interface and class
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.
But I am for consistency withFormInterface which has@return $this on methods likeaddError. Although I agree that fluent interfaces are pain.
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.
I've changed my mind and addedreturn $this; back in. I could see developers wanting to call$form->clearErrors()->createView() so this definitely has value.
The last unanswered question is what to do about return types. Our ultimate goal is to haveForm::clearErrors() return that originalForm instance. Here's what theReturn Type Declarations RFC has to say about our current situation:
The enforcement of the declared return type during inheritance is invariant; this means that when a sub-type overrides a parent method then the return type of the child must exactly match the parent and may not be omitted.
This is why using: self on the interface requires theForm method to use: ClearableErrorsInterface which is not ideal.
However, the RFC goes on to say:
If the parent does not declare a return type then the child is allowed to declare one.
Because this is a valid approach, I thinkomitting the return type from the interface but using: self on theForm makes the most sense in this situation:
- A return type on the interface is pointless because there are literally no other methods on
ClearableErrorsInterface. Is somebody really going to call$form->clearErrors()->clearErrors()->clearErrors()? - This gives us the functionality we want (accurate return type hint on
Form) despite PHP's current limitations with invariant return types.
c69e507 toed74efdCompare| * | ||
| * @return $this | ||
| */ | ||
| publicfunctionclearErrors(bool$deep =false):self |
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.
@xabbuh I have added a: self return type here per your request. See#27580 (comment) for an explanation of why I didn't also add a return type to the interface. Let me know your thoughts :)
colinodell commentedJun 20, 2018
Tests are failing, but I don't think it's because of my changes. All tests under |
ed74efd to9eb755cComparefabpot commentedJun 25, 2018
Thank you@colinodell. |
This PR was squashed before being merged into the 4.2-dev branch (closes#27580).Discussion----------[Form] Add ability to clear form errors| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets |#14060| License | MIT| Doc PR |symfony/symfony-docs#9916This PR adds the ability to manually clear form errors, thus improving the DX issue reported in#14060.Unlike my original approach in#14233 and#27571 which break BC, this adds a new `ClearableErrorInterface` which `Form` implements. (`Button` does not implement it because buttons can't have errors.)Commits-------9eb755c [Form] Add ability to clear form errors
fabpot commentedJun 25, 2018
Changelog added ina1eb649 (forgot to comment before merging) |
…uiluz)This PR was merged into the master branch.Discussion----------[Form] Ability to clear form errorsDocumenting the new feature proposed insymfony/symfony#27580Commits-------f07f536 Wrap long lines and add the versionadded directive7a4465d Clarify that clearing errors makes the form validd4143f1 [Form] Ability to clear form errors


Uh oh!
There was an error while loading.Please reload this page.
This PR adds the ability to manually clear form errors, thus improving the DX issue reported in#14060.
Unlike my original approach in#14233 and#27571 which break BC, this adds a new
ClearableErrorInterfacewhichFormimplements. (Buttondoes not implement it because buttons can't have errors.)