Varun
Varun

Reputation: 3735

Angular 2 Data binding not Working for Input Decorator

I'm trying to change the value for a Donut chart based on the Input Decorator. I'm able to initialize the value but cannot change it any further.

I'm using <input type="number" [(ngModel)]="complete"> to 2 way data bind the value. But its not working. I think it's not working because, the template is already called and we're changing the data later.

Is there any solution to this.?

Working code: http://plnkr.co/edit/hYlFp1BX8ebixQMqAtNj?p=preview

Parent component code:

@Component({
  selector: 'my-app',
  providers: [],
  template: `


    <test-component [complete]="complete"></test-component>
    Completed %:<input type="number" [(ngModel)]="complete">

  `,
  directives: [TestComponent]
})
export class App {
  complete:number=40;
  constructor(){

  }
  test(){
    this.complete=60;
  }
}

Upvotes: 0

Views: 1994

Answers (1)

acdcjunior
acdcjunior

Reputation: 135862

The complete value changes at the parent component are being received by the @Input() complete at the directive.

Your chart is the one not updating. You'll have to repaint the whole chart everytime the value changes.

My suggestion: make complete an Observable<integer> and push a new value everytime the user changes the complete <input>.

The relevant changes:

@Component({
    ...
    <test-component [complete]="complete"></test-component>
    Completed %:<input type="number" [(ngModel)]="complete">
...
export class App {
  complete:number=40;
  constructor(){

Becomes:

@Component({
    ...
    <test-component [complete]="completeObs"></test-component>
    Completed %:<input type="number" [(ngModel)]="complete" 
                                               (ngModelChange)="completeObs.next($event)">
...
export class App {
  complete:number=40;
  completeObs:Observable<integer> = new BehaviorSubject<integer>(this.complete);
  constructor(){

And you need to change the directive as well:

export class TestComponent{
  @Input() complete:Observable<integer>;

  ngAfterViewInit() {
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var colors=['green','orange'];
    var labels=['Completed','Pending'];

    this.complete.subscribe((complete) => {      // <-- notice it subscribes to the input
      let incomplete:integer = 100 - complete;

See plunker demo here.

Upvotes: 0

Related Questions