12

I have the following DOM structure

<div #carousalElement>
    <div  class="singleCaousalElement">
        <a>
            <img [src]="carousalURL1" class="carousalImage">
        </a>
    </div>
    <div  class="singleCaousalElement">
        <a>
            <img [src]="carousalURL2" class="carousalImage">
        </a>
    </div>
</div>

I can get the all divs with carousalElements class using the ViewChildren

@ViewChildren('carousalElement') carousalElements;

PROBLEM: When I dynamically add a new div under the #carousalElement div, it does not show up under the carousalElements array.

Am I missing something obvious?

Giridhar Karnik
  • 2,213
  • 4
  • 27
  • 47

4 Answers4

9

Angular doesn't recognize HTML not added by Angular directives or APIs. Also if the <div> doesn't have a template variable #carousalElement, @ViewChildren('carousalElement') won't find it.

Template variables need to be added statically in the components template. Adding them dynamically is meaningless. Angular processes Angular-specific template constructs only during compilation of a template.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
3

You can add the service ChangeDetectorRef and call the method this.changeDetectorRef.detectChanges() when you add another child with the ref that you have referenced in ViewChildren QueryList. That worked for me!

Gerard_dev
  • 703
  • 5
  • 7
0

At point when you add new element in your carousalElement div at that time check in DOM if that element is available or not.

If available get element by:

this.carousalElements.NativeElement......

If not available then try to set some timeout then after check again in DOM

setTimeout(() => {
        //your logic
    }, 200);

Still not find then try with below logic:

@ViewChildren('carousalElement', { read: ViewContainerRef })
public carousalElement: QueryList<ViewContainerRef>;

And where you check console.log(this.carousalElement)

Let me know what it gives

  • 1
    if I do `document.querySelectorAll('.singleCaousalElement')' I get the newly added div, so it means that it has been added, but the I am not able to reference it using the ViewChildren, since it has parsed the dom only during the ngOnInit and is not refreshing when new DOM elements are added. – Giridhar Karnik Apr 20 '17 at 05:02
0

In JavaScript there are two data types: primitive and object.

In Angular there are basically 3 data types (glossing over plenty here): primitive, object, and reactive. Without going into details

@ViewChildren('carousalElement') carousalElements;

Is of the data type reactive. In Angular, this means there is an observer in this case the amount of elements with the caoursalElement templateVariable, your variable carousalElements is an advanced form of subscription to @ViewChildren, which is an observer to access the updated array you simply need

()=>{return this.carousalElements}

Make sure your HTML template is using your template vars correctly and this should work

double-beep
  • 5,031
  • 17
  • 33
  • 41