Angular 2 save input form value bound to model using getter and setter

I would like to bind the input value to the model using getter and seters. This way I can prevent and / or manipulate the input value while writing inside it.

For example, I want the numbers placed inside the input field to be blocked. So, if the record "abc" is all right, then if I start writing the number, nothing should happen (with the model and with the input value). The problem is that with the following code, I can write something inside the input field (but the model is correct). This means that the value of the input field does not represent my model.

NOTE. The reason underlying this question is because I want to use my models to validate forms, preventing, for example, specific characters. I would not want to use reactive forms like . I want to keep my checks inside my models not components. Also note that in a real scenario, I will have a UserModel class with an internal name and other fields with their checks.

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2><input type="text" [(ngModel)]="name"> {{name}}</h2>
    </div>
  `,
})
export class App {
  _name:string = 'ss';
  constructor() {
  }

  // In real scenario those 2 methods are in a separate class UserModel
  get name() {
    return this._name;
  }

  set name() {
    if ((new RegExp(/^[a-zA-Z]*$/).test(val))) {
        this._name = val;
    }
  }
}
+4
source share
3 answers

Based on @ Günter Zöchbauer's answer, I made a workaround. It is not final and may be more abstract, but at the moment this is normal.

export class App implements OnInit {
    @Input() userModel: UserModel = null;
    public _vm;

    constructor(private _changeDetectionRef: ChangeDetectorRef) {
    }

    /**
     * Initalize view model, it important to keep names specular
     */
    ngOnInit() {
        this._vm = {
            name: this.userModel.name,
            surname: this.userModel.surname,
        };
    }

    /**
     * Helper for avoid detectchanges inside the modal, and reduce boilerplate. We could also ad an interface/type of the possibile field value, ie type fieldT= 'name' | 'surname';
     * @param field
     * @param val
     */
    protected updateModel(field, val: string): void {
        this._vm[field] = null;
        this._changeDetectionRef.detectChanges();
        this.userModel[field] = val;
        this._vm[field] = this.userModel[field];
        this._changeDetectionRef.detectChanges();
    }
}

In userModel:

....

    public get name(): string {
        return this.name';
    }

    public set name(val: string) {
        if ((new RegExp(/^[a-zA-Z]*$/).test(val))) {
            this.name = val;
        }
    }

In the template:

<input type="text"  name="userName"  [ngModel]="_vm.name" (ngModelChange)="updateModel('name', $event)">
+1
source

, , ngModel <input>

,

export class App {

  _name:string = 'ss';

  constructor(private cdRef:ChangeDetectorRef) {}

  get name() {
    return this._name;
  }

  set name(value:String) {
    this._name = value + 'x';
    this.cdRef.detectChanges()
  }
}

reset , , , detectChanges() .

  set name(value:String) {
    var oldVal = this._name;
    this._name = null;
    this.cdRef.detectChanges()
    this._name = oldVal;
    this.cdRef.detectChanges()
  }
+4

(ngModelChange) [ngModel] .

Plunker, , .

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2><input #input type="text" [ngModel]="name" (ngModelChange)='valid(input.value)'> {{name}}</h2>
    </div>
  `,
})
export class App {
  name:string = 'ss';
  constructor() {
  }

  valid(value){
    if(value){ //<--- Your test here
      this.name = value;
    }
  }

}
0

Source: https://habr.com/ru/post/1672546/


All Articles