21

How can I access the child elements (here: <img>) of @ViewChild() in Angular 2+ without explicit declaration?

In template.html

<div #parent>
  <!-- There can be anything than <img> -->
  <img src="http://localhost/123.jpg" alt="">
</div>

In component.ts

@ViewChild('parent') parent;

public getFirstChild() {
   this.firstChild = this.parent.? //
}

The aim is, to be able to create a universal component that uses:

<div #parent>
    <ng-content></ng-content>
</div>

So the child elements of #parent need to be accessible without explicit declaration.

Liam
  • 27,717
  • 28
  • 128
  • 190
btx
  • 1,972
  • 3
  • 24
  • 36

4 Answers4

28

You can use the nativeElement property of the ElementRef given by ViewChild to get the corresponding HTML element. From there, standard DOM methods and properties give access to its children:

  • element.children
  • element.querySelector
  • element.querySelectorAll
  • etc.

For example:

@ViewChild("parent") private parentRef: ElementRef<HTMLElement>;

public getChildren() {
  const parentElement = this.parentRef.nativeElement;
  const firstChild = parentElement.children[0];
  const firstImage = parentElement.querySelector("img");
  ...
}

See this stackblitz for a demo.

ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • Great, thanks! Might there be an additional Angular way to access the child elements? – btx Aug 13 '18 at 19:29
  • The "Angular way" would be with template reference variables, but I don't know if they can be used in transcluded content. – ConnorsFan Aug 13 '18 at 19:49
  • Awesome! This was the only thing I found to let me select a dynamically generated component of an unknown type injected in an ng-container with *ngComponentOutlet inside my parent component. – jpf Nov 20 '20 at 22:20
3

use ViewChildren instead which gets all elements with same tag.

@ViewChildren('parent') parents: QueryList<any>;

To convert those elements to array:

const arr = this.parent.toArray();

Choose first element:

const el = arr[0]

Access child html of first element: const innerHtml = el.nativeElement.innerHtml;

Vugar Abdullayev
  • 1,852
  • 3
  • 21
  • 46
  • But this doesn't access the , does it? I need to access the **child** of #parent – btx Aug 13 '18 at 18:47
  • Why you do not access img directly instead of through parent. If you have strong reason for than then you can use innerHtml to access child. const el = arr[0].nativeElement.innerHtml – Vugar Abdullayev Aug 13 '18 at 18:52
  • As I mentioned, the parent has dynamic content. So I don't want to have an explicit accessor for the content. – btx Aug 13 '18 at 19:22
0

In your case, when you need only one and first child.

this.parent.nativeElement.firstChild

Grzegorz S.
  • 1
  • 1
  • 2
0

HTML

<div #parent>
  <span id="child">
</div>

TS

 @ViewChild('parent',{static:false}) parentDiv:ElementRef
 this.parentDiv.nativeElement.firstChild

You can check this out if you want do any operations in it renderer2

Arokia Lijas
  • 441
  • 4
  • 14