-1

I have four components and I need to pass data from a parent to a child. The structure in the map.html template looks something likes this:

<map-builder [width]="width">
    <layer [name]="'markerLayer'">        
        <marker [lat]="8.5" [lng]="55.5"></marker>
        <marker [lat]="54" [lng]="8.5"></marker>
    </layer>
    <layer [name]="'heatmapLayer'">
        <heatmap></heatmap>
    </layer>
</map-builder>

In the LayerComponent I have the variables layer and source. In ngOnInit() I set both values. Now I need to access both values in the nested component (Marker and Heatmap). I tried to inject the LayerComponent in the constructor(), but I can't access its variables.

Thanks for the help!

Milo
  • 3,365
  • 9
  • 30
  • 44
Thalion
  • 31
  • 5
  • this is a classic example of utilizing `@Input()` mapping. have `marker` and `heatmap` components `@Input()` decorated properties `layer` and `source` and pass then down to child components. /Now, your additional comments to answers suggest you have some additional requirements you want to do. I would suggest putting them in question. – dee zg Nov 24 '17 at 17:33
  • In [this answer](https://stackoverflow.com/a/35267202/1009922), Günter Zöchbauer suggests a way to inject the parent in the child's constructor. – ConnorsFan Nov 24 '17 at 17:48
  • yes, with a notification: thightly coupling. which is directly against the whole point of components. if your child component is tightly coupled with its parent then you have to ask yourself why did you do a child component in the first place? component should be reusable and as documentation says, `Input()/Output()` should be its primary way of communication with 'outer world'. – dee zg Nov 25 '17 at 04:43
  • take a look at official docs: https://angular.io/guide/component-interaction – dee zg Nov 25 '17 at 04:48
  • And what about a service? Creating a layer and a source in the layerService, everytime a new layer comp is added. And in the marker/heatmap component I get its layer/source from the service. – Thalion Nov 27 '17 at 08:38

1 Answers1

1

use Input Decorator and make sure that layer and source properties are public in LayerComponent:

export class MarkerComponent implements OnInit {
    @Input() layer;
    @Input() source;
}

export class HeatMapComponent implements OnInit {
    @Input() layer;
    @Input() source;
}

html :

<map-builder [width]="width">
<layer #lyr [name]="'markerLayer'">        
    <marker [layer]="lyr.layer" [scoure]="lyr.source" [lat]="8.5" [lng]="55.5"></marker>
    <marker [layer]="lyr.layer" [scoure]="lyr.source" [lat]="54" [lng]="8.5"></marker>
</layer>
<layer #lyr2 [name]="'heatmapLayer'">
    <heatmap [layer]="lyr2.layer" [scoure]="lyr2.source" ></heatmap>
</layer>
</map-builder>

Or Inject the parent in the child's consturctor :

export class HeatMapComponent implements OnInit {
  constructor(private layer : LayerComponent){}

 ngOnInit(){
    //this.layer.source
    //this.layer.layer
   this.layer.onDataChange.subscribe((data)=>{
     console.log(data.layer,data.source)
   })
 }

in your layer Component

export class LayerComponent implements OnInit {
layer: any;
source: any;
@Output() onDataChange: EventEmitter<any> = new EventEmitter<any>();

someMethod() {
    // when you change the value emit them 
    this.layer = someValue;
    this.source = someValue;

    this.onDataChange.emit({ layer: this.layer, source: this.source })
}

you're getting undefined values because you try to access them before the get initialized

Demo

El houcine bougarfaoui
  • 35,805
  • 9
  • 37
  • 37
  • I know this is possible, but this looks so "unclean". Is there no other way? I dont want to add [layer] and [source] to every included feature (marker, heatmap ...) Furthermore I want a LayerObject component that handles the source and layer logic. All feature components such as marker or heatmap will be extended by the LayerObject. – Thalion Nov 24 '17 at 16:41
  • I alreay tried to inject it in the constructor. If I console.log(this.layer) it shows me the layer and the source. But if i try to read this.layer.layer or this.layer.source it says undefined. – Thalion Nov 24 '17 at 17:06
  • see the update bro, you access them before the get initialized – El houcine bougarfaoui Nov 24 '17 at 17:28
  • Can't test it with the full code, but it works on my home project so far. Thank you :) – Thalion Nov 24 '17 at 17:41