sohaieb azaiez
sohaieb azaiez

Reputation: 780

Set and Get accessors are not working for my angular component

I don't know why set & get accessors does not change anything in the value of _counter property? when i use this.propagateChange method in the set accessor it will not working, but when i used it inside incr() and decr() methods it worked correctly, so what is the problem please?

here is my codes :

button.component.ts

import {Component, forwardRef, Input, OnInit} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';

@Component({
  selector: 'app-button',
  templateUrl: './button.component.html',
  styleUrls: ['./button.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ButtonComponent),
      multi: true,
    }
  ]
})
export class ButtonComponent implements OnInit, ControlValueAccessor {
  _counter  = 0;
  @Input() step = 1;
  propagateChange;

  get counter() {
    return this._counter ;
  }

  set counter(value) {
    this._counter  = value;
    this.propagateChange(this._counter);
  }

  setDisabledState(isDisabled: boolean): void {
  }

  constructor() {
  }

  ngOnInit() {
  }

  incr() {
    this._counter  += this.step;
  }

  decr() {
    this._counter  -= this.step;
    /*this.propagateChange(this._counter);*/
  }

  registerOnChange(fn: any) {
    this.propagateChange = fn;
  }

  registerOnTouched(fn: any): void {
  }

  writeValue(obj: any): void {
    if (obj !== undefined) {
      this._counter  = obj;
    }
  }
}

button.component.html

<button (click)="incr()">+</button>
<button (click)="decr()">-</button>

app.component.ts

import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  prodForm: FormGroup;

  constructor(
    private fb: FormBuilder
  ) {
  }

  ngOnInit(): void {
    this.prodForm = this.fb.group(
      {
        counter: [0, Validators.required]
      }
    );
  }


}

app.component.html

<form [formGroup]="prodForm">
  <input [value]="prodForm.get('counter').value">
  <app-button formControlName="counter"></app-button>
</form>


Thanks.

Upvotes: 0

Views: 1312

Answers (3)

sohaieb azaiez
sohaieb azaiez

Reputation: 780

I solved my problem by changing this line :

export class ButtonComponent implements OnInit, ControlValueAccessor {
  _counter = 0;
  @Input() step = 1;
  propagateChange; ===> this is the problem
..
...
....

to this one:

export class ButtonComponent implements OnInit, ControlValueAccessor {
  _counter = 0;
  @Input() step = 1;
propagateChange: any = () => {}; ===> this is the answer
..
...
....

In addition to @Kamil Augustyniak ==> answer, I solved it.

Upvotes: 1

Handerson Contreras
Handerson Contreras

Reputation: 21

You have to reference this.counter = yourvalue ;

But you're referencing this._counter

Upvotes: 0

Kamil Augustyniak
Kamil Augustyniak

Reputation: 429

You should use _counter only inside getter and setter. Outside you have to use counter.

export class ButtonComponent implements OnInit, ControlValueAccessor {
  _counter = 0;
  @Input() step = 1;
  propagateChange;

  get counter() {
    return this._counter;
  }

  set counter(value) {
    this._counter = value;
    this.propagateChange(this._counter);
  }

  setDisabledState(isDisabled: boolean): void {
  }

  constructor() {
  }

  ngOnInit() {
  }

  incr() {
    this.counter += this.step;
  }

  decr() {
    this.counter -= this.step;
    /*this.propagateChange(this._counter);*/
  }

  registerOnChange(fn: any) {
    this.propagateChange = fn;
  }

  registerOnTouched(fn: any): void {
  }

  writeValue(obj: any): void {
    if (obj !== undefined) {
      this.counter = obj;
    }
  }
}

Upvotes: 1

Related Questions