Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular manually update ngModel and set form to dirty or invalid?

I have a form and an underlying model like this

From component

myTextModel: string;
updateMyTextModel(): void {
    this.myTextModel = "updated model value";
    //todo- set form dirty (or invalid or touched) here
}

Html template

<form #testForm="ngForm" id="testForm">
  <input type="text" id="myText" [(ngModel)]="myTextModel" name="myText" #myText="ngModel">
</form>
<button (click)="updateMyTextModel()">Update myTextModel</button>
<div *ngIf="testForm.dirty">testForm diry</div>
<div *ngIf="testForm.touched">testForm touched</div>

How do I set the form touched or dirty from code?

Note: In this example i use a button to trigger the model change, but i also might update the model in other ways, such as in a callback from an web api async request.

like image 386
Toby Avatar asked Dec 01 '17 08:12

Toby


People also ask

How do you make Angular forms dirty?

You should use the markAsDirty method, like this: control. markAsDirty(); This will also mark all direct ancestors as dirty to maintain the model.

How do I update my ngModel value?

If we use two way binding syntax for ngModel the value will be updated. So the default (ngModelChange) function will update the value of ngModel property. i.e., user.Name . And the second (ngModelChange) will be triggered printing the user name value in the console.

What is form dirty in Angular?

When the user changes the value in the watched field, the control is marked as "dirty" When the user blurs the form control element, the control is marked as "touched"


3 Answers

Solution:

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { Component, ViewChild } from '@angular/core';
import { FormsModule }   from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <form #testForm="ngForm" id="testForm">
        <input type="text" id="myText" [(ngModel)]="myTextModel" name="myText" #myText="ngModel">
    </form>
    <button (click)="updateMyTextModel()">Update myTextModel</button>
    <div *ngIf="testForm.dirty">testForm diry</div>
    <div *ngIf="testForm.touched">testForm touched</div>
  `,
})
export class App {

  @ViewChild('testForm') test: any;

  updateMyTextModel(){
    this.test.control.markAsTouched();
    this.test.control.markAsDirty();

  }

  constructor() {
    console.log(this.test);
  }
}

@NgModule({
  imports: [ BrowserModule,FormsModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

Plunkr working:

https://plnkr.co/edit/YthHCEp6iTfGPVcNr0JF?p=preview

like image 198
Daniel Segura Pérez Avatar answered Oct 13 '22 15:10

Daniel Segura Pérez


Why not use Reactive forms (FormGroup),

let testForm = new FormGroup({
    myText: new FormControl('initial value')
})

<form [formGroup]="testForm">
    <input type="text" formControlName="myText">
</form>

<button (click)="updateMyTextModel()">Update myTextModel</button>
<div *ngIf="testForm.dirty">testForm diry</div>
<div *ngIf="testForm.touched">testForm touched</div>

In your function, you can use markAsDirty() based on whatever condition you want.

updateMyTextModel(): void {
    this.myTextModel = "updated model value";
    if ( // some condition ) {
        this.testForm.markAsDirty();
    }
}

To set individual form controls as dirty/touched, you can use

this.testForm.get('myText').markAsDirty();
this.testForm.get('myText').markAsTouched();
like image 6
cyberpirate92 Avatar answered Oct 13 '22 16:10

cyberpirate92


This should work:

@ViewChild('testForm') testForm;


updateMyTextModel(): void {
    this.myTextModel = "updated model value";
    this.myForm.form.markAsDirty();
}
like image 3
Riscie Avatar answered Oct 13 '22 15:10

Riscie