You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
Repository navigation
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
In order to implement on blur, there needs to be more states to forms then just pristine and dirty. The gold standard should be to validate all the time, but updating the UI only when user navigates away from the widget.
People have been struggling with premature validation, where the form inputs are marked as invalid before the user even touches the form. I recommended that they use .ng-dirty.ng-invalid but the problem is this does not change when the user submits.
It appears there are no class changes to the form when a submit of the form is attempted (regardless of fail or pass).
I have created a demo that shows a simple fix for this: http://plnkr.co/edit/172Vlv?p=preview and caters to both scenarios (premature validation and skipping validation altogether) from a visual perspective.
tl;dr
Remove the ng-pristine class and add some sort of ng-submitted class when the form is submitted. I'd prefer to have this on the actual form/ng-form directive rather than a third party directive.
I've been struggling with this as well; ng-pristine / NgModelController.$pristine, as implemented, isn't especially useful. The user needs at least some chance to enter information correctly before being scolded.
A state which is set once the user has interacted with, but then left, the control would be appropriate. (i.e. blur has been fired)
Not actually @caitp, i'm addressing the case when a user sees a Form and instantly presses the submit button having no interaction with any of its components. There, the way I see it, it would desirable to point out which fields are required for example. That's why an $attempted state would be very adequate.
@matsko what you are calling $submitted is very close to what I'm thinking of.
The difference resides in two aspects.
attempted adjective seems more suitable than submitted, because it may not be due to failed validations.
I thought of $attempted just for Forms, don't know how it would fit in Inputs.
In that particular case, it still sounds like something which could be accomplished with ng-submit + $pristine, since the FormController's $pristine should be true if all of its controls are pristine, or even just iterating over all of the forms controls.
It might be possible to make implementing this more elegant, but it should already be quite possible (of course, this requires the submit event to happen, but I guess you could bind a click event to the submit button also to make whatever changes happen that need to happen)
Note, I'm not saying we shouldn't try to make this nicer, I'm just saying you might be able to solve your problem adequately already
The gist was that you would create a template snippet which would switch between all the different input types, automatically generating labels, surrounding html (<div class="form-group"> etc), error messages, and so forth. The idea was that you would generally declare a template either app-wide or form-wide, etc. which would contain all the above scenarios (and have a dictionary of validation messages keyed by validation rule name). This way you define your validation messages for the FORM instead of each input. We wanted to have it handle things like automatically generating the name and id and for (for labels) properties based on the ng-model.
Example:
<scripttype="text/ng-template" id="vert-form"><divclass="form-group"ng-class="{error:$input.error}"><ng-switchon="$input.type"><textareang-switch-when="textarea"name="{{$input.name}}"></textarea>
...
</ng-switch><divclass="help"ng-repeat="(errorName, error) in $input.$errors"ng-switch="errorName"><spanng-switch-when="required">The {{$input.name}} field cannot be left empty</span>...
</div></div></script><formname="vert-form"><!-- or <div ng-form="vert-form"> --><ui-inputtype="textarea" ng-model="data.item" requiredmax-length="3" /><!-- or <ui-input template="vert-form" ...> to override/specify on a field-by-field basis --></form>
The type property was used to select which chunk of the template you were leveraging, the ng-model was expanded into id's, names, and for-properties (all namespaced by the <form> or ng-form).
The $input was a scope utility to access things such as formName.inputName.$error but also transclusion and properties of the <ui-input> and finally interpolated properties to make things easier like a $input.id or $input.name which could of course be explicitly overwritten on the ui-input tag.
The Problem:
The big issue we ran into however was that we wanted to transclude to a few different places in the resultant template, AND we weren't able to use {{}} on the name property and get it to work. Using repeaters on form inputs also proved difficult when trying to generate names or ids since <input id="input[{{$index}}]" name="input[{{$index}}]"> doesn't work.
#5888 I've send a PR for adding a $dirtyAfter state for controls, which could greatly improve the decision to display or not inline validation messages. For example, an inline validation message can be shown using the condition "myForm.myField.$dirty || myForm.myField.$dirtyAfter".
I also think a form level "attempted" state would be a great idea, and it would work well along $dirtyAfter by using the following condition for showing/hiding inline validation messages "myForm.$attempted || myForm.myField.$dirty || myForm.myField.$dirtyAfter"
Yes, you're right.
But it seems strange to indicate that a field has been "touched" when it has not been changed, just focus and blur events.
No?
At the beggining of this issue, someone said that show errors while user type is a bad thing.
If I click by mistake on input (focus) then elsewhere (blur), $touched is set to true.
If I use $touched state, I immediately shows an error message. This is bad.
If I use $touched and $dirty state, I do not display an error. Good. BUT, the next time I'm updating this input, the error message appears immediately because $touched has already been set to true and $dirty will be on true, too.
$touched was specifically implemented for the case that a user tabs through a form and leaves inputs invalid. It happens far more often that you blur an input and leave it invalid, then accidentially clicking an input, then blurring it.
You can further control your error display behavior with the form field's $viewValue. Except for required errors, you could only display errors when the user has input something.
On the other hand, display an error while you just begin to type an email "Invalid email !!!" is a bad practice.
So, ok, it seems that $touched is not the information I need, but I think this information is missing: "This field has been changed and the user has just left it, so now, do what you want as validation or displaying messages or anything else"
It sounds like the condition you need is $touched && $dirty
On Sep 28, 2014 10:23 PM, "Renaud LITTOLFF" [email protected]
wrote:
Ok, so i don't understand the use case.
On the other hand, display an error while you just begin to type an email
"Invalid email !!!" is a bad practice.
So, ok, it seems that $touched is not the information I need, but I think
this information is missing: "This field has been changed and the user
has just left it, so now, do what you want as validation or displaying
messages or anything else"
—
Reply to this email directly or view it on GitHub #583 (comment).
@shahata: This won't work for the particular scenario @marmotz described: When the user clicks on the element, clicks away then clicks again and edits. It will be $touched and $dirty while editing (and not after blurring), because the field was $touched already.
Nonetheless, it is a very far-fetched and "corner-case-y" scenario and adding states to identify every possible weird user interraction with form-controls would create a mess with very small benefit (imo).
In any case, it is trivial to create a directive that sets the controls state to $untouched on blur if the input is not $dirty (and even automatically attach it to all <input> elements without changing your HTML). (Demo fiddle)
@gkalpak thanks for the demo but I already did my own directive like yours :)
In fact, i think it's not a "corner-case-y" scenario.
I try to have a good user experience with form and message.
The current system ($dirty, $touched, etc..) does not provide the ability to display an error message only at the end (blur, submit)
@marmotz: There a probably a dozen different use-cases that different people might want to support. Adding 2 properties ($xyz, $unxyz) and 2 methods ($setXyz(), $setUnxyz()) to the NgModelController for each such case will create a messy API (not to mention how internally all those properties would need to be managed, propagated etc).
The current properties provide support for enough use-cases "out of the box" and adding extra behaviour is super easy with Angular, so I don't see a reason to one extra pair of properties and methods for detecting a user's focusing a field, blurring a field then focusing again.
Hm...reading your comments again seems like you are not suggesting a new property, but a change in when the $touched property gets set. So it's a matter of what scenario comes up more frequently: Tab through the form and leave inputs invalid or focus-blur-focus.
My intuition is that (as @Narretz said) the current implementation will be more useful most of the time.
I'm going to close this issue since I believe that we added the states that we initially wanted to add. If there are any left over issues please open new issues. thanks!
...Actually perhaps they are really the same thing, just a different name? As in it $submitted gets set just before calling the ng-submit handler? I probably need to keep what I have anyway for other reasons.
Activity
ProLoser commentedon Sep 6, 2012
People have been struggling with premature validation, where the form inputs are marked as invalid before the user even touches the form. I recommended that they use
.ng-dirty.ng-invalidbut the problem is this does not change when the user submits.It appears there are no class changes to the form when a submit of the form is attempted (regardless of fail or pass).
I have created a demo that shows a simple fix for this: http://plnkr.co/edit/172Vlv?p=preview and caters to both scenarios (premature validation and skipping validation altogether) from a visual perspective.
tl;dr
Remove the
ng-pristineclass and add some sort ofng-submittedclass when the form is submitted. I'd prefer to have this on the actual form/ng-form directive rather than a third party directive.mullr commentedon Sep 24, 2012
I've been struggling with this as well; ng-pristine / NgModelController.$pristine, as implemented, isn't especially useful. The user needs at least some chance to enter information correctly before being scolded.
A state which is set once the user has interacted with, but then left, the control would be appropriate. (i.e.
blurhas been fired)wlingke commentedon Dec 6, 2013
I agree with the above. $dirty is too aggressive - users shouldn't be shown an error UI state until after they've blurred out of the element.
MisterK commentedon Dec 23, 2013
+1
nicoabie commentedon Dec 27, 2013
A useful state would be $attemped.
Its use case being when the user tries to submit without filling in and required fields should be highlighted.
caitp commentedon Dec 27, 2013
can't you already use the dirty state for that?
matsko commentedon Dec 27, 2013
Not sure how this issue came up again, but...
We've already planned this out and the solution is to have a few extra states:
The forms themselves are pretty good, but there needs to be more control over when messages are displayed. These flags should fill that hole.
nicoabie commentedon Dec 28, 2013
Not actually @caitp, i'm addressing the case when a user sees a Form and instantly presses the submit button having no interaction with any of its components. There, the way I see it, it would desirable to point out which fields are required for example. That's why an $attempted state would be very adequate.
@matsko what you are calling $submitted is very close to what I'm thinking of.
The difference resides in two aspects.
Thanks to both of you for your replies, regards.
caitp commentedon Dec 28, 2013
In that particular case, it still sounds like something which could be accomplished with ng-submit + $pristine, since the FormController's $pristine should be true if all of its controls are pristine, or even just iterating over all of the forms controls.
It might be possible to make implementing this more elegant, but it should already be quite possible (of course, this requires the submit event to happen, but I guess you could bind a click event to the submit button also to make whatever changes happen that need to happen)
Note, I'm not saying we shouldn't try to make this nicer, I'm just saying you might be able to solve your problem adequately already
nicoabie commentedon Dec 28, 2013
You are right @caitp, it is possible to achieve the way you described. I actually used this directive http://code.realcrowd.com/on-the-bleeding-edge-advanced-angularjs-form-validation/
but it seems to me this should be angular's the concept of $attempted.
jeffbcross commentedon Jan 11, 2014
Here is @matsko's design doc for improving forms: https://docs.google.com/a/google.com/document/d/192dCUnoIBQ7-vurvPeS9BElGdxfk0Ddcof2KzDDi1Mc/edit
ProLoser commentedon Jan 11, 2014
@jeffbcross @matsko So honestly, the @angular-ui team tried to tackle simplifying form validation a few different times with ui-input:
The gist was that you would create a template snippet which would switch between all the different input types, automatically generating labels, surrounding html (
<div class="form-group">etc), error messages, and so forth. The idea was that you would generally declare a template either app-wide or form-wide, etc. which would contain all the above scenarios (and have a dictionary of validation messages keyed by validation rule name). This way you define your validation messages for the FORM instead of each input. We wanted to have it handle things like automatically generating the name and id and for (for labels) properties based on the ng-model.Example:
The
typeproperty was used to select which chunk of the template you were leveraging, theng-modelwas expanded into id's, names, and for-properties (all namespaced by the<form>orng-form).The
$inputwas a scope utility to access things such asformName.inputName.$errorbut also transclusion and properties of the<ui-input>and finally interpolated properties to make things easier like a$input.idor$input.namewhich could of course be explicitly overwritten on theui-inputtag.The Problem:
The big issue we ran into however was that we wanted to transclude to a few different places in the resultant template, AND we weren't able to use
{{}}on the name property and get it to work. Using repeaters on form inputs also proved difficult when trying to generate names or ids since<input id="input[{{$index}}]" name="input[{{$index}}]">doesn't work.matsko commentedon Jan 13, 2014
@ProLoser let's figure out the naming system first so that all the new features can actually be possible.
troch commentedon Jan 19, 2014
#5888 I've send a PR for adding a $dirtyAfter state for controls, which could greatly improve the decision to display or not inline validation messages. For example, an inline validation message can be shown using the condition "myForm.myField.$dirty || myForm.myField.$dirtyAfter".
I also think a form level "attempted" state would be a great idea, and it would work well along $dirtyAfter by using the following condition for showing/hiding inline validation messages "myForm.$attempted || myForm.myField.$dirty || myForm.myField.$dirtyAfter"
21 remaining items
mdsauer commentedon Sep 12, 2014
Thanks @Narretz . My initial thought was to call a $setUntouched method but I do not see that method on the form in 1.3 RC1. Is it being added?
Narretz commentedon Sep 12, 2014
Oh, true. It's only available on the ngModelController. We should probably add it.
marmotz commentedon Sep 28, 2014
For now, $touched is set to true on blur event.
If user click on input then click elsewhere, $touched was set to true while there is no change.
Why not set $touched to true only if the value has been changed ?
gkalpak commentedon Sep 28, 2014
@marmotz: Isn't that what
$dirtyis (sort of) for ?marmotz commentedon Sep 28, 2014
Yes, you're right.
But it seems strange to indicate that a field has been "touched" when it has not been changed, just focus and blur events.
No?
At the beggining of this issue, someone said that show errors while user type is a bad thing.
If I click by mistake on input (focus) then elsewhere (blur), $touched is set to true.
You see what I mean?
Narretz commentedon Sep 28, 2014
$touched was specifically implemented for the case that a user tabs through a form and leaves inputs invalid. It happens far more often that you blur an input and leave it invalid, then accidentially clicking an input, then blurring it.
You can further control your error display behavior with the form field's $viewValue. Except for required errors, you could only display errors when the user has input something.
marmotz commentedon Sep 28, 2014
Ok, so i don't understand the use case.
On the other hand, display an error while you just begin to type an email "Invalid email !!!" is a bad practice.
So, ok, it seems that
$touchedis not the information I need, but I think this information is missing: "This field has been changed and the user has just left it, so now, do what you want as validation or displaying messages or anything else"shahata commentedon Sep 29, 2014
It sounds like the condition you need is
$touched && $dirtyOn Sep 28, 2014 10:23 PM, "Renaud LITTOLFF" [email protected]
wrote:
gkalpak commentedon Sep 29, 2014
@shahata: This won't work for the particular scenario @marmotz described: When the user clicks on the element, clicks away then clicks again and edits. It will be
$touched and $dirtywhile editing (and not after blurring), because the field was$touchedalready.Nonetheless, it is a very far-fetched and "corner-case-y" scenario and adding states to identify every possible weird user interraction with form-controls would create a mess with very small benefit (imo).
In any case, it is trivial to create a directive that sets the controls state to
$untouchedon blur if the input is not$dirty(and even automatically attach it to all<input>elements without changing your HTML). (Demo fiddle)marmotz commentedon Sep 29, 2014
@gkalpak thanks for the demo but I already did my own directive like yours :)
In fact, i think it's not a "corner-case-y" scenario.
I try to have a good user experience with form and message.
The current system ($dirty, $touched, etc..) does not provide the ability to display an error message only at the end (blur, submit)
Demo: http://jsfiddle.net/marmotz/orcsjyLs/2/
It's a "corner-case-y" scenario ?
gkalpak commentedon Sep 29, 2014
@marmotz: There a probably a dozen different use-cases that different people might want to support. Adding 2 properties (
$xyz,$unxyz) and 2 methods ($setXyz(),$setUnxyz()) to the NgModelController for each such case will create a messy API (not to mention how internally all those properties would need to be managed, propagated etc).The current properties provide support for enough use-cases "out of the box" and adding extra behaviour is super easy with Angular, so I don't see a reason to one extra pair of properties and methods for detecting a user's focusing a field, blurring a field then focusing again.
Hm...reading your comments again seems like you are not suggesting a new property, but a change in when the
$touchedproperty gets set. So it's a matter of what scenario comes up more frequently: Tab through the form and leave inputs invalid or focus-blur-focus.My intuition is that (as @Narretz said) the current implementation will be more useful most of the time.
IgorMinar commentedon Sep 30, 2014
I'm going to close this issue since I believe that we added the states that we initially wanted to add. If there are any left over issues please open new issues. thanks!
darrenshrwd commentedon Dec 2, 2015
Can someone confirm that there was never any implementation of $attempted?
$submitted not so useful to me so I'll continue using custom code like @nicoabie based on: http://code.realcrowd.com/on-the-bleeding-edge-advanced-angularjs-form-validation/
...Actually perhaps they are really the same thing, just a different name? As in it $submitted gets set just before calling the ng-submit handler? I probably need to keep what I have anyway for other reasons.
Narretz commentedon Dec 2, 2015
@darrenshrwd No, $attempted was never implemented. Depending on your use case, $pristine together with $submitted might be the way to go.