ContentChildren, get component and native element

I've searched forever in Angular documentation and source code but no luck so far.

import {
  ContentChildren,
  QueryList
} from '@angular/core';
import { AwesomeComponent } from './awesome.component';

@Component({
  selector: 'cool-dad',
  templateUrl: './cool-dad.template.html'
})
export class CoolDadComponent {
  @Input() loop = false;
  @Input() automatic = false;
  @ContentChildren(AwesomeComponent) items: QueryList<AwesomeComponent>;

  someFunc() {
    this.items.forEach(item => { console.log(item)});
  }
}

      

With the above code, I get a reference to the component, I can set its properties and call it public methods. This is great, but I also need access to its html properties like width, height, etc.

import {
  ContentChildren,
  ElementRef,
  QueryList
} from '@angular/core';
import { AwesomeComponent } from './awesome.component';

@Component({
  selector: 'cool-dad',
  templateUrl: './cool-dad.template.html'
})
export class CoolDadComponent {
  @Input() loop = false;
  @Input() automatic = false;
  @ContentChildren(AwesomeComponent, { read: ElementRef }) items: QueryList<AwesomeComponent>;

  someFunc() {
    this.items.forEach(item => { console.log(item)});
  }
}

      

With the above code, I am getting my own element and therefore can access all the html properties, but I lost all access to the component methods.

How can I get both?

+3


source to share


2 answers


Just declare the following in the constructor AwesomeComponent:

constructor(public elem: ElementRef) {}

      



This way you will be able to access the public property element and access the html properties of each component:

someFunc() {
 this.items.forEach(item => {console.log(item.elem.nativeElement.style.someHTMLProperty)});
}

      

+1


source


After a hack to make this work on my own project, I figured out why it's not natively supported in any way: it's a bad idea.

If CoolDadComponent

can actually change the properties of HTML AwesomeComponent

, then obviously different assumptions need to be made about that component and encapsulation goes up. Also, looking at the encapsulation rules can complicate the style.

So, the correct way to do this is to let you CoolDadComponent

work with @ContentChildren

and set properties on instances AwesomeComponent

. These instances should manipulate their own HTML, preferably in a template, or at least with Renderer

.

export class CoolDadComponent {
// Other stuff as in OP
  @ContentChildren(AwesomeComponent) items: QueryList<AwesomeComponent>;
  someFunc() {
    this.items.forEach(item => item.configure({prop1: 'value', prop2: 'value'}));
  }
}

      



And in AwesomeComponent

:

export class AwesomeComponent {
// Other stuff
  public configure(options: MyOptionsInterface) {
    // Set related properties
  }

      

It will also work if CoolDadComponent

(bonus points for that name, by the way) just sets the custom properties to AwesomeComponent

directly.

+1


source







All Articles