Material: ngMessages is not working as expected

Created on 22 Dec 2015  路  38Comments  路  Source: angular/material

I am using ngMessage with angular material. But it doesn't working as expected. I have my code here.

The problem is once the error message is displayed, when another new error is appeared and the existing error is disappeared then it breaks. For above example, click on the input and click outside of it. You will receive the required error. Now when you try inserting any character, the required error disappeared and the email error should appear. But this is not working.

urgent

Most helpful comment

I resolved this adding 'ngMessages' in my modules 卢卢

All 38 comments

<div ng-app="app" ng-controller="FormController" layout-padding>
  <form name="inputForm">
    <md-input-container>
      <label>Input Value</label>
      <input type="email" name="email" ng-required="true" ng-pattern="/^.+@.+\..+$/" ng-model="model.value" />
      <div ng-messages="inputForm.email.$error">
        <div ng-message-exp="['required', 'pattern']">E-mail is not valid</div>
      </div>
    </md-input-container> 
    <div>inputForm.inputValue.$error = {{inputForm.email.$error | json}}</div>
  </form>
</div>

I have the same issue with the newest update of material and angular

Another issue here is that error message does not show initially for required input field.

on the last bit, I think it is by design... I have discussed this with users a number of times, and they don't seem to like being presented with error messages until they at least enter something, so the idea that ng-messages are hidden until the related field has been $touched seems good to me.

Messages that should be displayed even before the user interacts with a field seem to me to be labels or input hints.

Same issue here on ng-material 1.0.0, 1.0.1 and angular 1.4.6 and 1.4.8.

Update: adding md-auto-hide="false" solves my problems. I can now add ng-show="form2.username.$touched" to hide on page load and voila, I'm golden.

@FrancescoRizzi: I thought so. At least we need a way to enable this.
And suggestion from @rsteenbergen is exactly what we need. This is also described in docs.

I think the hide animation works after the element appears into the display section. So it hides all messages. Is there any way to solve the issue temporarily?

@rsteenbergen thanks - that helped me

NgMessage behave erratically with angular-material. Here is a plunker: http://embed.plnkr.co/SWJFsOS3BuxYxePBQZ0C/

It works fine with just the required validation check, but if I add another, like min for instance, then sometimes the error message isn't shown at all.
Without angular-material it works fine.

Form Without Angular-Material
_Initial_
screen shot 2016-01-22 at 4 37 53 pm

_When I enter a value < 400:_
2

Form With Angular-Material
_I enter a small value:_
screen shot 2016-01-22 at 4 38 38 pm

_I erase everything:_
screen shot 2016-01-22 at 4 38 31 pm

_I enter a value greater than 400 and then erase everything:_
screen shot 2016-01-22 at 4 38 51 pm

UPDATE: Fixed it thanks to @rsteenbergen, linked plunker now has updated code.

So this is resolved?

Well @rsteenbergen provided a workaround, but is that the solution we want? Shouldnt it 'just work' with ngMessages instead of users having to add rsteenbergen's solution.

I'm seeing the same problem and agree with @joerideg . It is erratic so I hesitate to use the md-hide workaround to get it to work more often.

Update: While I have noticed strange behavior with the appearance of the messages, this time it was my mistake. I accidentally left off the input's name attribute. Sorry!

Using md-auto-hide="false" isn't a great fix, since all errors will display by default, which can be overwhelming for someone filling out a new empty form.

I have the same problem here with angular 1.5.0 and angular-material 1.0.5. Also after I updated angular-material from 1.0.1 the error pushes content down instead of appearing in md-errors-spacer

you can see it's even in official demo https://material.angularjs.org/latest/demo/input

Confirming this too (angular 1.5.0 + angular-material 1.0.5).

Any fix on this?

+1

+1

same here

+1

I resolved this adding 'ngMessages' in my modules 卢卢

+1

+1 Not sure what the solution is here. It seems like the ngMessages module doesn't finish the animation so it never removes the ng-hide hide class from the message and the ng-messages container.

I don't fully understand the problem but I found a solution based on the comments about. The why I got rid of the accidental ng-hide class is by explicitly stating that ng-show on the ngMessages directive for each condition. It seems like a bit of a hack but it works.

I put <pre>{{loginForm.email.$error | json }} in the code so I know what properties to target. It seems to work perfect. Hopefully, this bug will be solved in the near future.

                    <md-input-container class="md-block">
                        <input type="email"
                               name="email"
                               ng-model="vm.form.email"
                               placeholder="Email"
                               ng-pattern=/^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/
                               required
                               aria-label="Email"
                               aria-invalid="false"/>
                        <div ng-messages="loginForm.email.$error"
                             role="alert"
                             aria-live="assertive"
                             ng-show="loginForm.email.$error.email || loginForm.email.$error.required">
                            <div ng-message="required"><span>Email field is required</span></div>
                            <div ng-message="pattern"><span>Email must be a valid e-mail address</span></div>
                        </div>
                    </md-input-container>

+1

:+1:

+1

+1

This issue has opened on Dec 22, do we expect the fix in this year or shall we wait another year for the fix?

you can try this solution @iamisti

.md-input.ng-invalid.ng-touched + .md-errors-spacer + [ng-messages] > div {
opacity: 1 ;
margin-top: 0;
}
.md-input.ng-invalid.ng-touched + .md-errors-spacer + [ng-messages] > div.ng-leave , .md-input.ng-invalid.ng-touched + .md-errors-spacer + [ng-messages] > div.ng-enter {
position: absolute !important;
}

.md-input.ng-invalid.ng-touched + .md-errors-spacer + [ng-messages] > div.ng-leave , .md-input.ng-invalid.ng-touched + .md-errors-spacer + [ng-messages] > div.ng-enter-active{
opacity: 1 !important;
margin-top: 0 !important;
}
.md-input.ng-invalid.ng-touched + .md-errors-spacer + [ng-messages] > div.ng-leave-active , .md-input.ng-invalid.ng-touched + .md-errors-spacer + [ng-messages] > div.ng-enter {
opacity: 0 !important;
margin-top: -19px !important;
}
Same issue here on ng-material 1.0.0, 1.0.1 and angular 1.4.6 and 1.4.8.

Update: adding md-auto-hide="false" solves my problems. I can now add ng-show="form2.username.$touched" to hide on page load and voila, I'm golden.

Thanks @rsteenbergen for this tricky solution.
But with this solution, the message blinks at first time it displays (v1.0.7)

This issue is closed as part of our 鈥楽urge Focus on Material 2' efforts.
For details, see our forum posting.

This issue is closed as part of our 鈥楽urge Focus on Material 2' efforts.
For details, see our forum posting @ http://bit.ly/1UhZyWs.

This issue is closed as part of our 鈥楽urge Focus on Material 2' efforts.
For details, see our forum posting @ http://bit.ly/1UhZyWs.

So first, I realize that this issue has been deprecated/closed as part of the _Surge Focus on Material 2_.
However, for those of you who want a proper fix read on.

But first, a little history for the _TL;DR_ folks.

This issue only happens when there are 2 or more ng-message containers within the ng-messages container.

@rsteenbergen provided a workaround (aka hack) for the div containing the ng-messages attribute directive that alleviated this issue:

adding md-auto-hide="false" solves my problems. I can now add ng-show="form2.username.$touched" to hide on page load and voila, I'm golden.

This works, but it presents what I would call a 'jitter' issue. Which is basically, for lack of better explanation, when the same validation message has the ngMaterial _showMessage_ animation applied twice in quick succession.

As @joerideg said

Well @rsteenbergen provided a workaround, but is that the solution we want? Shouldnt it 'just work' with ngMessages instead of users having to add rsteenbergen's solution.

Well here is the fix I have used for angular-1.5.8 using angular-material-1.1.0-rc.5.

In the ngMaterial::input::ngMessageAnimation.enter function, add the piece in bold

// If we have the md-auto-hide class, the md-input-invalid animation will fire, so we can skip
if (messages.childElementCount === 1 && messages.hasClass('md-auto-hide')) {
done();
return;
}

TL;DR
Apply the above change to the function _ngMessageAnimation()_ in
node_modules/angular-material/angular-material.js

See also

6872

8635

@nknowles88 thanks for the effort for those who still need this fix, but, i highly recommenced not to change the node_modules for two reasons:

  1. When working with a team, that means every single person should do it
  2. When we will release versions, your changes will be deleted

please, if you do want to help and get this issue resolve, suggest a PR and we will work to get it in.

Alright here is another solution that doesn't involve modifying vendor code.

  • Extend the md-input-messages-animation css class so that it partially mimics what md-auto-hide is doing and place it in your application's css file. If you don't want to extend the css class call it something else. It really doesn't matter.
md-input-container .md-input-messages-animation .md-input-message-animation:not(.ng-animate) {
  margin-top:-100px;
  opacity:0;
}
  • On the container that has ng-messages="myForm.myField.$error" add md-auto-hide="false"
<md-input-container class="md-block">
  <label>Email</label>
  <input type="email" name="myField"
         ng-model="$ctrl.formData.myField"
         required/>
   <div ng-messages="myForm.myField.$error" 
        md-auto-hide="false" role="alert">
     <div ng-message="required">This is required!</div>
     <div ng-message="email">Must be a valid email address</div>
   </div>
</md-input-container>

This has the side effect of showing error messages as soon as the user starts typing in the input field. To retain the full effect of md-auto-hide, replace md-auto-hide="false" with ng-class="{'md-auto-hide':myForm.myEmail.$untouched}".


@EladBezalel To make sure my prior suggestion didn't have any lingering effects, I deleted my entire node_modules folder and ran npm install to pull everything down again.

@nknowles88 thanks for helping everyone encountering this issue,
IMO it would be even more helpful if you can actually solve this issue and suggest a PR :smile:
thanks either way!

@EladBezalel This issue has been fixed already in the master branch 6a7a188 (which is 220 commits ahead of 1.1.0-rc.5).

Edit: here is the commit that fixed it fa6213d

I cloned the master, built the project and used the build artifacts to update/replace the angular-material 1.1.0-rc.5 node_module files that my project's build process uses.

I'm not familiar with this project's resolution process, but IMO this issue is a candidate for closure once a new release is made.

Was this page helpful?
0 / 5 - 0 ratings