Modifying Form Value As User Types









up vote
0
down vote

favorite












I'm trying to modify an input value as a user types. Consider this simplified example:



app.component.html



<label for="testInput">Enter Text Here: </label>
<input
id="testInput"
type="text"
[ngModel]="inputVal"
(ngModelChange)="handleChange($event)"
>


app.component.ts



import Component from '@angular/core';

@Component(
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
)
export class AppComponent
inputVal: string = '';
handleChange(newVal)
let justDigits = newVal.replace(/[^0-9]/g, '');
console.log('The new value with just digits: ', justDigits);
this.inputVal = justDigits;




The console log clearly shows that handleChange is running and strips out non-digits. However, the form value doesn't reflect that. For instance if you were to type '123abc', the form value would display just that. The console log would show '1', then '12', then '123' four times.



Coming from a lot of React, this is bizarre. What's going on here?










share|improve this question

















  • 1




    you need to understand how ngModelChange works . Everytime the input changes , ngModelChange is called . If you type 1 , ngModelChange is called . and then again ngModelChange is called when you type 2 next . Everytime , your input is changing and hence the console.log prints 1 ,12, 123,123 , 123 , 123 (last 3 times 123 is due to replace() ) . This is how angular works and how ngModelChange works .
    – CruelEngine
    Nov 12 at 4:25











  • I suggest you to use (keyup) event instead of (ngModelChange)
    – Hardik
    Nov 12 at 4:52










  • @CruelEngine The surprising was not the console log. That worked as I expected. The surprising thing was that setting inputVal did not change the input displayed to the user.
    – canyonCreek
    Nov 12 at 13:34














up vote
0
down vote

favorite












I'm trying to modify an input value as a user types. Consider this simplified example:



app.component.html



<label for="testInput">Enter Text Here: </label>
<input
id="testInput"
type="text"
[ngModel]="inputVal"
(ngModelChange)="handleChange($event)"
>


app.component.ts



import Component from '@angular/core';

@Component(
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
)
export class AppComponent
inputVal: string = '';
handleChange(newVal)
let justDigits = newVal.replace(/[^0-9]/g, '');
console.log('The new value with just digits: ', justDigits);
this.inputVal = justDigits;




The console log clearly shows that handleChange is running and strips out non-digits. However, the form value doesn't reflect that. For instance if you were to type '123abc', the form value would display just that. The console log would show '1', then '12', then '123' four times.



Coming from a lot of React, this is bizarre. What's going on here?










share|improve this question

















  • 1




    you need to understand how ngModelChange works . Everytime the input changes , ngModelChange is called . If you type 1 , ngModelChange is called . and then again ngModelChange is called when you type 2 next . Everytime , your input is changing and hence the console.log prints 1 ,12, 123,123 , 123 , 123 (last 3 times 123 is due to replace() ) . This is how angular works and how ngModelChange works .
    – CruelEngine
    Nov 12 at 4:25











  • I suggest you to use (keyup) event instead of (ngModelChange)
    – Hardik
    Nov 12 at 4:52










  • @CruelEngine The surprising was not the console log. That worked as I expected. The surprising thing was that setting inputVal did not change the input displayed to the user.
    – canyonCreek
    Nov 12 at 13:34












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm trying to modify an input value as a user types. Consider this simplified example:



app.component.html



<label for="testInput">Enter Text Here: </label>
<input
id="testInput"
type="text"
[ngModel]="inputVal"
(ngModelChange)="handleChange($event)"
>


app.component.ts



import Component from '@angular/core';

@Component(
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
)
export class AppComponent
inputVal: string = '';
handleChange(newVal)
let justDigits = newVal.replace(/[^0-9]/g, '');
console.log('The new value with just digits: ', justDigits);
this.inputVal = justDigits;




The console log clearly shows that handleChange is running and strips out non-digits. However, the form value doesn't reflect that. For instance if you were to type '123abc', the form value would display just that. The console log would show '1', then '12', then '123' four times.



Coming from a lot of React, this is bizarre. What's going on here?










share|improve this question













I'm trying to modify an input value as a user types. Consider this simplified example:



app.component.html



<label for="testInput">Enter Text Here: </label>
<input
id="testInput"
type="text"
[ngModel]="inputVal"
(ngModelChange)="handleChange($event)"
>


app.component.ts



import Component from '@angular/core';

@Component(
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
)
export class AppComponent
inputVal: string = '';
handleChange(newVal)
let justDigits = newVal.replace(/[^0-9]/g, '');
console.log('The new value with just digits: ', justDigits);
this.inputVal = justDigits;




The console log clearly shows that handleChange is running and strips out non-digits. However, the form value doesn't reflect that. For instance if you were to type '123abc', the form value would display just that. The console log would show '1', then '12', then '123' four times.



Coming from a lot of React, this is bizarre. What's going on here?







angular






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 at 3:59









canyonCreek

436




436







  • 1




    you need to understand how ngModelChange works . Everytime the input changes , ngModelChange is called . If you type 1 , ngModelChange is called . and then again ngModelChange is called when you type 2 next . Everytime , your input is changing and hence the console.log prints 1 ,12, 123,123 , 123 , 123 (last 3 times 123 is due to replace() ) . This is how angular works and how ngModelChange works .
    – CruelEngine
    Nov 12 at 4:25











  • I suggest you to use (keyup) event instead of (ngModelChange)
    – Hardik
    Nov 12 at 4:52










  • @CruelEngine The surprising was not the console log. That worked as I expected. The surprising thing was that setting inputVal did not change the input displayed to the user.
    – canyonCreek
    Nov 12 at 13:34












  • 1




    you need to understand how ngModelChange works . Everytime the input changes , ngModelChange is called . If you type 1 , ngModelChange is called . and then again ngModelChange is called when you type 2 next . Everytime , your input is changing and hence the console.log prints 1 ,12, 123,123 , 123 , 123 (last 3 times 123 is due to replace() ) . This is how angular works and how ngModelChange works .
    – CruelEngine
    Nov 12 at 4:25











  • I suggest you to use (keyup) event instead of (ngModelChange)
    – Hardik
    Nov 12 at 4:52










  • @CruelEngine The surprising was not the console log. That worked as I expected. The surprising thing was that setting inputVal did not change the input displayed to the user.
    – canyonCreek
    Nov 12 at 13:34







1




1




you need to understand how ngModelChange works . Everytime the input changes , ngModelChange is called . If you type 1 , ngModelChange is called . and then again ngModelChange is called when you type 2 next . Everytime , your input is changing and hence the console.log prints 1 ,12, 123,123 , 123 , 123 (last 3 times 123 is due to replace() ) . This is how angular works and how ngModelChange works .
– CruelEngine
Nov 12 at 4:25





you need to understand how ngModelChange works . Everytime the input changes , ngModelChange is called . If you type 1 , ngModelChange is called . and then again ngModelChange is called when you type 2 next . Everytime , your input is changing and hence the console.log prints 1 ,12, 123,123 , 123 , 123 (last 3 times 123 is due to replace() ) . This is how angular works and how ngModelChange works .
– CruelEngine
Nov 12 at 4:25













I suggest you to use (keyup) event instead of (ngModelChange)
– Hardik
Nov 12 at 4:52




I suggest you to use (keyup) event instead of (ngModelChange)
– Hardik
Nov 12 at 4:52












@CruelEngine The surprising was not the console log. That worked as I expected. The surprising thing was that setting inputVal did not change the input displayed to the user.
– canyonCreek
Nov 12 at 13:34




@CruelEngine The surprising was not the console log. That worked as I expected. The surprising thing was that setting inputVal did not change the input displayed to the user.
– canyonCreek
Nov 12 at 13:34












2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted










Your problem is change detection, if you type in '1a2b3c' you will see the following on the page itself:



1
1a
12
12b
123
123c



This is because inputVal doesn't change if your input ends with letters.



A possible solution is to trigger change detection. This can be done as follows:



import Component, ChangeDetectorRef from '@angular/core';

@Component(
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
)
export class AppComponent
inputVal: string = '';

constructor(private cdr: ChangeDetectorRef)

handleChange(newVal)
let justDigits = newVal.replace(/[^0-9]/g, '');
console.log('The new value with just digits: ', justDigits);
this.inputVal = null; // Change the model and trigger a change detection
this.cdr.detectChanges();
this.inputVal = justDigits;// Change it again, and let the change detection happen




Stackblitz: https://stackblitz.com/edit/angular-l14ehr






share|improve this answer



























    up vote
    0
    down vote













    For this kind of scenario, the best would be to have pipe. In your case you can have pipe which will filter everything except number.



    Here the NumberDirective which allow numbers only.



    import Directive, ElementRef, HostListener, Input from '@angular/core';
    import NgControl from '@angular/forms';

    @Directive(
    selector: 'input[numbersOnly]'
    )
    export class NumberDirective

    constructor(private _el: ElementRef)

    @HostListener('input', ['$event']) onInputChange(event)
    const initalValue = this._el.nativeElement.value;
    this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
    if (initalValue !== this._el.nativeElement.value)
    event.stopPropagation();






    Here is the working demo - https://stackblitz.com/edit/angular-numbers-only-directive-2qm1cc






    share|improve this answer




















    • Sure. But I'm more interested in figuring out why this isn't working...
      – canyonCreek
      Nov 12 at 13:31










    • This also doesn't work, the value doesn't reach the model: stackblitz.com/edit/angular-numbers-only-directive-c3efi1
      – Aviad P.
      Nov 12 at 18:02










    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255788%2fmodifying-form-value-as-user-types%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote



    accepted










    Your problem is change detection, if you type in '1a2b3c' you will see the following on the page itself:



    1
    1a
    12
    12b
    123
    123c



    This is because inputVal doesn't change if your input ends with letters.



    A possible solution is to trigger change detection. This can be done as follows:



    import Component, ChangeDetectorRef from '@angular/core';

    @Component(
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
    )
    export class AppComponent
    inputVal: string = '';

    constructor(private cdr: ChangeDetectorRef)

    handleChange(newVal)
    let justDigits = newVal.replace(/[^0-9]/g, '');
    console.log('The new value with just digits: ', justDigits);
    this.inputVal = null; // Change the model and trigger a change detection
    this.cdr.detectChanges();
    this.inputVal = justDigits;// Change it again, and let the change detection happen




    Stackblitz: https://stackblitz.com/edit/angular-l14ehr






    share|improve this answer
























      up vote
      1
      down vote



      accepted










      Your problem is change detection, if you type in '1a2b3c' you will see the following on the page itself:



      1
      1a
      12
      12b
      123
      123c



      This is because inputVal doesn't change if your input ends with letters.



      A possible solution is to trigger change detection. This can be done as follows:



      import Component, ChangeDetectorRef from '@angular/core';

      @Component(
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
      )
      export class AppComponent
      inputVal: string = '';

      constructor(private cdr: ChangeDetectorRef)

      handleChange(newVal)
      let justDigits = newVal.replace(/[^0-9]/g, '');
      console.log('The new value with just digits: ', justDigits);
      this.inputVal = null; // Change the model and trigger a change detection
      this.cdr.detectChanges();
      this.inputVal = justDigits;// Change it again, and let the change detection happen




      Stackblitz: https://stackblitz.com/edit/angular-l14ehr






      share|improve this answer






















        up vote
        1
        down vote



        accepted







        up vote
        1
        down vote



        accepted






        Your problem is change detection, if you type in '1a2b3c' you will see the following on the page itself:



        1
        1a
        12
        12b
        123
        123c



        This is because inputVal doesn't change if your input ends with letters.



        A possible solution is to trigger change detection. This can be done as follows:



        import Component, ChangeDetectorRef from '@angular/core';

        @Component(
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
        )
        export class AppComponent
        inputVal: string = '';

        constructor(private cdr: ChangeDetectorRef)

        handleChange(newVal)
        let justDigits = newVal.replace(/[^0-9]/g, '');
        console.log('The new value with just digits: ', justDigits);
        this.inputVal = null; // Change the model and trigger a change detection
        this.cdr.detectChanges();
        this.inputVal = justDigits;// Change it again, and let the change detection happen




        Stackblitz: https://stackblitz.com/edit/angular-l14ehr






        share|improve this answer












        Your problem is change detection, if you type in '1a2b3c' you will see the following on the page itself:



        1
        1a
        12
        12b
        123
        123c



        This is because inputVal doesn't change if your input ends with letters.



        A possible solution is to trigger change detection. This can be done as follows:



        import Component, ChangeDetectorRef from '@angular/core';

        @Component(
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
        )
        export class AppComponent
        inputVal: string = '';

        constructor(private cdr: ChangeDetectorRef)

        handleChange(newVal)
        let justDigits = newVal.replace(/[^0-9]/g, '');
        console.log('The new value with just digits: ', justDigits);
        this.inputVal = null; // Change the model and trigger a change detection
        this.cdr.detectChanges();
        this.inputVal = justDigits;// Change it again, and let the change detection happen




        Stackblitz: https://stackblitz.com/edit/angular-l14ehr







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 12 at 5:35









        Aviad P.

        17.8k77395




        17.8k77395






















            up vote
            0
            down vote













            For this kind of scenario, the best would be to have pipe. In your case you can have pipe which will filter everything except number.



            Here the NumberDirective which allow numbers only.



            import Directive, ElementRef, HostListener, Input from '@angular/core';
            import NgControl from '@angular/forms';

            @Directive(
            selector: 'input[numbersOnly]'
            )
            export class NumberDirective

            constructor(private _el: ElementRef)

            @HostListener('input', ['$event']) onInputChange(event)
            const initalValue = this._el.nativeElement.value;
            this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
            if (initalValue !== this._el.nativeElement.value)
            event.stopPropagation();






            Here is the working demo - https://stackblitz.com/edit/angular-numbers-only-directive-2qm1cc






            share|improve this answer




















            • Sure. But I'm more interested in figuring out why this isn't working...
              – canyonCreek
              Nov 12 at 13:31










            • This also doesn't work, the value doesn't reach the model: stackblitz.com/edit/angular-numbers-only-directive-c3efi1
              – Aviad P.
              Nov 12 at 18:02














            up vote
            0
            down vote













            For this kind of scenario, the best would be to have pipe. In your case you can have pipe which will filter everything except number.



            Here the NumberDirective which allow numbers only.



            import Directive, ElementRef, HostListener, Input from '@angular/core';
            import NgControl from '@angular/forms';

            @Directive(
            selector: 'input[numbersOnly]'
            )
            export class NumberDirective

            constructor(private _el: ElementRef)

            @HostListener('input', ['$event']) onInputChange(event)
            const initalValue = this._el.nativeElement.value;
            this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
            if (initalValue !== this._el.nativeElement.value)
            event.stopPropagation();






            Here is the working demo - https://stackblitz.com/edit/angular-numbers-only-directive-2qm1cc






            share|improve this answer




















            • Sure. But I'm more interested in figuring out why this isn't working...
              – canyonCreek
              Nov 12 at 13:31










            • This also doesn't work, the value doesn't reach the model: stackblitz.com/edit/angular-numbers-only-directive-c3efi1
              – Aviad P.
              Nov 12 at 18:02












            up vote
            0
            down vote










            up vote
            0
            down vote









            For this kind of scenario, the best would be to have pipe. In your case you can have pipe which will filter everything except number.



            Here the NumberDirective which allow numbers only.



            import Directive, ElementRef, HostListener, Input from '@angular/core';
            import NgControl from '@angular/forms';

            @Directive(
            selector: 'input[numbersOnly]'
            )
            export class NumberDirective

            constructor(private _el: ElementRef)

            @HostListener('input', ['$event']) onInputChange(event)
            const initalValue = this._el.nativeElement.value;
            this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
            if (initalValue !== this._el.nativeElement.value)
            event.stopPropagation();






            Here is the working demo - https://stackblitz.com/edit/angular-numbers-only-directive-2qm1cc






            share|improve this answer












            For this kind of scenario, the best would be to have pipe. In your case you can have pipe which will filter everything except number.



            Here the NumberDirective which allow numbers only.



            import Directive, ElementRef, HostListener, Input from '@angular/core';
            import NgControl from '@angular/forms';

            @Directive(
            selector: 'input[numbersOnly]'
            )
            export class NumberDirective

            constructor(private _el: ElementRef)

            @HostListener('input', ['$event']) onInputChange(event)
            const initalValue = this._el.nativeElement.value;
            this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
            if (initalValue !== this._el.nativeElement.value)
            event.stopPropagation();






            Here is the working demo - https://stackblitz.com/edit/angular-numbers-only-directive-2qm1cc







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 12 at 8:35









            Sunil Singh

            6,1472626




            6,1472626











            • Sure. But I'm more interested in figuring out why this isn't working...
              – canyonCreek
              Nov 12 at 13:31










            • This also doesn't work, the value doesn't reach the model: stackblitz.com/edit/angular-numbers-only-directive-c3efi1
              – Aviad P.
              Nov 12 at 18:02
















            • Sure. But I'm more interested in figuring out why this isn't working...
              – canyonCreek
              Nov 12 at 13:31










            • This also doesn't work, the value doesn't reach the model: stackblitz.com/edit/angular-numbers-only-directive-c3efi1
              – Aviad P.
              Nov 12 at 18:02















            Sure. But I'm more interested in figuring out why this isn't working...
            – canyonCreek
            Nov 12 at 13:31




            Sure. But I'm more interested in figuring out why this isn't working...
            – canyonCreek
            Nov 12 at 13:31












            This also doesn't work, the value doesn't reach the model: stackblitz.com/edit/angular-numbers-only-directive-c3efi1
            – Aviad P.
            Nov 12 at 18:02




            This also doesn't work, the value doesn't reach the model: stackblitz.com/edit/angular-numbers-only-directive-c3efi1
            – Aviad P.
            Nov 12 at 18:02

















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255788%2fmodifying-form-value-as-user-types%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            27

            Top Tejano songwriter Luis Silva dead of heart attack at 64

            Category:Rhetoric