9

I have a component in angular 4 that is called three times. In template metadata I have a div with a directive with some bindings like this.

@import {gServ} from '../gServ.service';

@Component: ({
   selector: 'sr-comp',
   template: `<div gDirective [cOptions]="dataChart">`
})

export class SGComponent implements OnInit {
    @Input('report') public report: IReportInstance;
    cOptions:any;

    constructor(private gServ: gServ) {
    }

    ngOnInit(){

        this.cOptions = {};
        this.cOptions = this.gServ.objectMerge(this.gServ.defaultOpt, this.report.opt);

        //this.report.opt is binded to a component when is instantiated.
        //this.gServ.objectMerge is a function that merge the two objects
    }
}

this.cOptions change for every instance of the component, then in the directive I have this:

import { Directive, ElementRef, HostListener, Input, OnInit } from '@angular/core';

@Directive({
  selector: '[gDirective]'
})
export class SGDirective implements OnInit {
  public _element: any;
  @Input() public cOptions: string;

  constructor(public element: ElementRef) {
    this._element = this.element.nativeElement;
  }

  ngOnInit() {
    console.log(this.cOptions);
  }
}

The problem is that console.log(this.cOptions); always print the same object, even when component set cOptions with diferent values in ngOnInit method of the compnent.

Do you have some idea what is wrong?

xzegga
  • 3,051
  • 3
  • 25
  • 45

3 Answers3

3

Your component property binding [cOptions]="dataChart" doesn't look good, reason being your dataChart is not even defined. it should be like [DIRECTIVE_PROPERTY]="COMPONENT_PROPERTY" and your COMPONENT_PROPERTY is not even defined in SGComponent component class.

Your component class should be something like this:

@import {gServ} from '../gServ.service';

@Component: ({
   selector: 'sr-comp',
   template: `<div gDirective [cOptions]="Options">`
})

export class SGComponent implements OnInit {
    @Input('report') public report: IReportInstance;
    Options:any;

    constructor(private gServ: gServ) {
    }

    ngOnInit(){
        this.Options = {};
        this.Options = this.gServ.objectMerge(this.gServ.defaultOpt, this.report.opt);
    }
} 
Ashwani Kumar
  • 216
  • 2
  • 14
0

@Ashwani points out a valid problem with your code. The way your template is wiring things up, nothing will ever be passed to the SGDirective input.

Another potential problem you could be running into has to do with the gServ code. If gServ is a singleton (which is probably the case) and it is returning the same object to each of the SGComponents, then all the SGDirectives will have the same value. A simple way to test this is to put {{Options | json}} in the SGComponent template.

To create a new instance of the gServ service for each SGComponent you can add a providers array to the @Component metadata. It would look like this:

import {gServ} from '../gServ.service';

@Component({
   selector: 'sr-comp',
   template: `{{Options | json}}<div gDirective [cOptions]="Options"></div>`
   providers: [gServ],
})

export class SGComponent implements OnInit {
    @Input('report') public report: IReportInstance;
    Options:any;

    constructor(private gServ: gServ) {
    }

    ngOnInit(){
        this.Options = this.gServ.objectMerge(this.gServ.defaultOpt, this.report.opt);
    }
}
Isaac
  • 2,173
  • 1
  • 13
  • 15
0

You have probably the same return/value at this.gServ.objectMerge) (you can test it wihtout calling the service, and passing each one one different objet make by you)

@import {gServ} from '../gServ.service';

@Component: ({
   selector: 'sr-comp',
   template: `<div gDirective [cOptions]="dataChart">`
})

export class SGComponent implements OnInit {
    //@Input('report') public report: IReportInstance;
    cOptions:any;

    constructor(private gServ: gServ) {
    }

    ngOnInit(){

        this.cOptions = {nicolas: 'nicolas1'}; //change this in the next component that use the directive

    }
}

If that is the case, your problem is that gServ is provide at the same rootComponent. with angular, service provider at the same rootComponent are singleton.

And use the same type in your directive and your component!!

nicearma
  • 750
  • 2
  • 8
  • 21