17

I know this has been asked before, but none of the selected answers are working for me.

I am trying to use @ViewChild to get my ng-select from the dom. And it always returns undefined.

here is the select inside the main.html:

<ng-select id = "user-select" 
     #userSelect 
     [allowClear]="true"
     [items]="singleSignOnUsers"
     [disabled]="disabled"
     placeholder="No user selected">
</ng-select>

here is my component

import { Component, AfterViewInit, ViewChild  } from '@angular/core';

@Component({
    moduleId: module.id,
    selector: 'app-main',
    templateUrl: '../app/main.html',
    providers: [ApiHttpService, UserAdministrationService]
})

export class AppComponent {
    @ViewChild('userSelect') userSelect;


    ngAfterViewInit() {
        alert(this.userSelect);
    }
}

what am i missing here?

Update: Oh My Soul! I figured out why this wasn't working when it should.

I have the whole view wrapped in a div with an ngSwitch. If I move it out I can access them.

Now I don't know how to access them while in the ngSwitch however. But I don't have to use the ngSwitch.

<div [ngSwitch]='loading'>
        <div *ngSwitchCase="false">
            ...
            <ng-select id="user-select"
                       #userSelect
                       [allowClear]="true"
                       [items]="singleSignOnUsers"
                       [disabled]="disabled"
                       placeholder="No city selected">
            </ng-select>
            ...
        </div>
    <div
anastaciu
  • 23,467
  • 7
  • 28
  • 53
twaldron
  • 2,722
  • 7
  • 40
  • 55

4 Answers4

17

@twaldron Are you using some delayed data loading in ngOnInit?

Because in that case, in my experience, reading a @ViewChild as a ElementRef produces no results

If your component has the data already resolved (like the case when a parent passes a child data object to a sub component) it should work (at least for me it did).

In the case of asynchronous data loading, the way I was able to make it work is using a change notification

 @ViewChildren('userSelect') userSelect: QueryList<ElementRef>;

 ngAfterViewInit(): void {
    this.userSelect.changes.subscribe(item => {
        if (this.userSelect.length) {
            alert(this.userSelect.first.nativeElment.outerHTML)
        }
    })
 }
Florin D
  • 1,610
  • 18
  • 17
  • Thant makes sense I believe. I have it wrapped in the ngSwitch which shows a loading gif while the data is aquired async. When the data is done loading it is then switched and the element is shown. Ultimately I will be setting the items property of the select to the loaded data which is why i am trying to access it in the first place. – twaldron Nov 04 '16 at 19:48
  • This worked for me `ngAfterViewInit` and `ngOnInit` too. Thanks. – Kushal Jayswal Jun 10 '20 at 14:04
1

I replaced all occurrences of

*ngIf="flag"

with

[style.display]="flag ? 'block' : 'none'"

to get this to work consistently in my case. Otherwise the ViewChild components that didn't exist when my view first loaded would potentially remain undefined for ever.

Sreeram Nair
  • 2,369
  • 12
  • 27
0

In my case, I encountered the same problem. I console.log()-ed the content that is retrieved from the child component and it gives me 'undefined'.

And I solved it by merely refreshing the page. ctrl+shift+R may help. I guess it's because the cache of the browser that leads to this problem.

swanf
  • 79
  • 7
0

ngSwitch was exactly the reason. (and for that case ngIf doesn't work either)

Fixed it using classes so that it still renders everything and just hides it.

CSS

.show{
  display: block !important;
}

.hide{
  display: none;
}

HTML

 <div [ngClass]="{'show': someVariable === 'someVariable'}" class="hide">
   <input type="text" #search />
 </div>

Edit: the answer of @Sreeram Nair also works, even a bit more elegant.

Ruan
  • 3,969
  • 10
  • 60
  • 87