Skip to content

ngmodelOptions.updateon: 'blur' and input onblur event updating model value only for the first time #30653

Open

Description

@swathianupuram

I have a textbox which has ngModel, ngModelOptions(updateOn: 'blur') and it has onblur event handler. Now i am validating input value on blur event callback and if the value is less than 100 i will show error message and i will empty the text box value.

Issue: If I enter the value lessthan 100 then the textbox value is clearing properly only for the first time. From second time onwards the value is not emptied.

for example: enter 12 in input box and blur the input box we are getting the error message and it is lessthan 100 so value is set to empty(""). Now, i remove the 12 in input box and entered 55 this time the error message is showing up but the value is not clearing. It is showing the previous value.

Note: I tried to trigger angular change detection(detechChanges()) on blur event(after setting value to empty) even though the value is not clearing second time onwards.

can you please have a look at the stackblitz link(https://stackblitz.com/edit/angular-oyzcf8?file=src/app/app.component.ts) and let me know if there is anything I am missing here. Thanks

Activity

  1. EmaGht commented on May 27, 2019

    @EmaGht

    I'm not 100% up to speed with Angular's internals so i might be not completely correct in my explanation.

    When the user writes a number lesser than 100, you are resetting the value to "", if at this point the user writes again a number lesser than 100, the variable changes to, say, 20, but then gets instantly reset to "".

    This means that during Angular's CD you will always have a check like "" != "" for consecutive lesser-than-100 numbers.

    To fix this, you have to "give Angular time" to process the previous input, and only after that you can assign the new, empty value.

    This "give Angular time" translates to waiting the javascript stack to be executed and only then reset your input. Which in turn means that your line

    this.datavalue = "";

    needs to be changed to

    setTimeout(()=>{this.datavalue = ""});

    I've been using Angular for a couple years now and trust me, sooner or later, you'll spam "setTimeout"s everywhere

  2. added this to the needsTriage milestone on May 28, 2019
  3. jasonaden commented on May 28, 2019

    @jasonaden
    Contributor

    Just playing with the example, if you change to a value that is greater than 100, then back to a value under 100, it works again.

    Thanks for the issue. There seems to be odd behavior with change detection here. Yes, the solution above does work, but shouldn't be required.

  4. modified the milestones: needsTriage, Backlog on May 28, 2019
  5. EmaGht commented on May 29, 2019

    @EmaGht

    @jasonaden I have encountered this issue since Angular 2.0 to be honest... my entire application is built around feeding Angular's change detection with the right data at the right time.

    If this is actually an Angular's bug that's gonna be pretty big

  6. ElisePatrikainen commented on Jul 10, 2019

    @ElisePatrikainen

    As mentioned previously, the reason is probably that the same event (the blur event) is used to trigger an update of the value of the "AppComponent.datavalue" (the variable associated with the NgModel directive).
    These 2 updates are done by :

    • the NgModel directive (operation 1)
    • the callback handleChange() (operation 2)

    Only after these 2 operations, the Change detector will compare the "AppComponent.datavalue" values before and after the event. If there is a change, it will update the new value in the template. The problem is that sometimes (actually when user enters twice a number < 100), operation 2 cancels the change which was made by operation 1
    => the change detector doesn't see any change and doesn't update the template.

    Therefore the change detector has to be called between operation 1 and operation 2 (I could not format code but there is a link to a demo after):

    handleChange(event) { // The ngModel directive already updated the datavalue variable // = operation 1 is done if (this.datavalue < 100) { this.msg = 'please enter the value greaterthan 100'; // we call the change detector before the operation 2 this.cd.detectChanges(); // operation 2 this.datavalue = ""; } else { this.msg = ""; } } }

    Here is the code demo : https://stackblitz.com/edit/angular-1aldzw

    Nb: the first time the user enters a value in the input is always working because, even if operation 2 may remove the user's value (if value < 100), it actually defines the variable "AppComponent.datavalue" and assign it the value "", so there is a detectable change.

  7. Ajay070792 commented on Jul 7, 2020

    @Ajay070792

    @ElisePatrikainen solution is not working for me. Is there any other solutions to this problem?

    Thanks in advance.

  8. added
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    and removed on Oct 1, 2020
  9. mgohin commented on Nov 19, 2021

    @mgohin

    Calling the this.cd.detectChanges(); before setting the new value in my form did work for me. Thanks !

    May I suggest @ElisePatrikainen that you use a code block in your answer so it'll be more pleasant to read :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      Sponsor
      SponsoredKunjungi sekarang
      Promo