Angular 2 viewchild not working - cannot read property nativeElement of undefined
<p>I have this component called multiselect.component and I access one of its html elements <code>(&lt;select id="category-select"&gt;)</code> in the .ts file.</p>

<p>multiselect.component.html:</p>

<pre><code>&lt;select id="category-select" multiple class="form-control"&gt;
    &lt;option value="1"&gt;Meat&lt;/option&gt;
    &lt;option value="2"&gt;Dairy&lt;/option&gt;
    &lt;option value="3"&gt;Confectionary&lt;/option&gt;
    &lt;option value="4"&gt;Dessert&lt;/option&gt;
    &lt;option value="7"&gt;Baking&lt;/option&gt;
    &lt;option value="6"&gt;Grocers&lt;/option&gt;
    &lt;option value="5"&gt;Restaurants&lt;/option&gt;
    &lt;option value="8"&gt;Condiments&lt;/option&gt;
    &lt;option value="9"&gt;beverages&lt;/option&gt;
&lt;/select&gt;
&lt;div class="form-control-icon" id="keywords-icon"&gt;&lt;/div&gt;
</code></pre>

<p>multiselect.component.ts:</p>

<pre><code>import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'multiselect',
    templateUrl: 'app/shared/multiselect.component.html',
    styleUrls: [ 'app/shared/multiselect.component.css' ]
})
export class MultiselectComponent implements OnInit {
    items = 'one two three'.split(' ');
    selectedCategories;
    allSelected;
    numberOfCategories = 9;

    ngOnInit() {
        this.selectedCategories = [];
        (&lt;any&gt;$("#category-select")).multiselect({
            buttonWidth: '100%',
            buttonContainer: '&lt;div style="height: 34px;" /&gt;',
            buttonClass: 'none',
            nonSelectedText: "select categories",
            nSelectedText: ' categories',
            allSelectedText: "all categories",
            selectAllNumber: false,
            includeSelectAllOption: true,
            disableIfEmpty: true,
            onSelectAll: () =&gt; {
                this.allSelected = true;
            },
            onInitialized: () =&gt; {

            },
            onChange: (option, checked) =&gt; {
                this.changed();
            }
        });
    }

    changed() {
        this.selectedCategories = [];
        var self = this;

        $('#category-select option:selected').each(function () {
            self.selectedCategories.push(
                &lt;any&gt;($(this).text(), $(this).val())
            )
        });
        console.log(this.selectedCategories);
        if (this.selectedCategories.length &lt; this.numberOfCategories) {
            this.allSelected = false;
        }
    }
}
</code></pre>

<p>I think that the way I access it is bad practice by using jquery. I think it can be accessed with @viewChild instead.</p>

<p>So I'm trying to change it like this (I am first just getting rid of the first jquery element accessor then will do the rest later):</p>

<pre><code>import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
    selector: 'multiselect',
    templateUrl: 'app/shared/multiselect.component.html',
    styleUrls: [ 'app/shared/multiselect.component.css' ]
})
export class MultiselectComponent implements OnInit {
    items = 'one two three'.split(' ');
    selectedCategories;
    allSelected;
    numberOfCategories = 9;

    @ViewChild('category-select') select;

    ngOnInit() {
        this.selectedCategories = [];
        this.select.nativeElement.multiselect({
            buttonWidth: '100%',
            buttonContainer: '&lt;div style="height: 34px;" /&gt;',
            buttonClass: 'none',
            nonSelectedText: "select categories",
            nSelectedText: ' categories',
            allSelectedText: "all categories",
            selectAllNumber: false,
            includeSelectAllOption: true,
            disableIfEmpty: true,
            onSelectAll: () =&gt; {
                this.allSelected = true;
            },
            onInitialized: () =&gt; {

            },
            onChange: (option, checked) =&gt; {
                this.changed();
            }
        });
    }

    changed() {
        this.selectedCategories = [];
        var self = this;

        $('#category-select option:selected').each(function () {
            self.selectedCategories.push(
                &lt;any&gt;($(this).text(), $(this).val())
            )
        });
        console.log(this.selectedCategories);
        if (this.selectedCategories.length &lt; this.numberOfCategories) {
            this.allSelected = false;
        }
    }
}
</code></pre>

<p>I'm getting this console error:</p>

<pre><code>&gt; EXCEPTION: Error: Uncaught (in promise): EXCEPTION: Error in app/find-page/find-form.component.html:0:56
ORIGINAL EXCEPTION: TypeError: Cannot read property 'nativeElement' of undefined
ORIGINAL STACKTRACE:
TypeError: Cannot read property 'nativeElement' of undefined
    at MultiselectComponent.System.register.context_1.execute.MultiselectComponent.ngOnInit (http://localhost:3000/js/app/shared/Multiselect.component.js:29:32)
    at DebugAppView._View_FindFormComponent0.detectChangesInternal (FindFormComponent.ngfactory.js:761:90)
    at DebugAppView.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12586:18)
    at DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12691:48)
    at DebugAppView.AppView.detectViewChildrenChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12612:23)
    at DebugAppView._View_FindPageComponent0.detectChangesInternal (FindPageComponent.ngfactory.js:41:8)
    at DebugAppView.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12586:18)
    at DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12691:48)
    at DebugAppView.AppView.detectViewChildrenChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12612:23)
    at DebugAppView.AppView.detectChangesInternal (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12597:18)
ERROR CONTEXT:
[object Object]
</code></pre>

<p>Why am I getting that error?</p>

<p><strong>After changing to AfterViewInit, I'm now getting this error:</strong></p>

<pre><code>platform-browser.umd.js:937 Error: Uncaught (in promise): EXCEPTION: Error in app/find-page/find-form.component.html:13:30
ORIGINAL EXCEPTION: TypeError: Cannot read property 'length' of undefined
ORIGINAL STACKTRACE:
TypeError: Cannot read property 'length' of undefined
    at DebugAppView._View_FindFormComponent0.detectChangesInternal (FindFormComponent.ngfactory.js:890:72)
    at DebugAppView.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12586:18)
    at DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12691:48)
    at DebugAppView.AppView.detectViewChildrenChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12612:23)
    at DebugAppView._View_FindPageComponent0.detectChangesInternal (FindPageComponent.ngfactory.js:41:8)
    at DebugAppView.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12586:18)
    at DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12691:48)
    at DebugAppView.AppView.detectViewChildrenChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12612:23)
    at DebugAppView.AppView.detectChangesInternal (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12597:18)
    at DebugAppView.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12586:18)
ERROR CONTEXT:
[object Object]
    at resolvePromise (http://localhost:3000/node_modules/zone.js/dist/zone.js:538:32)
    at http://localhost:3000/node_modules/zone.js/dist/zone.js:515:14
    at ZoneDelegate.invoke (http://localhost:3000/node_modules/zone.js/dist/zone.js:323:29)
    at Object.onInvoke (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:9245:45)
    at ZoneDelegate.invoke (http://localhost:3000/node_modules/zone.js/dist/zone.js:322:35)
    at Zone.run (http://localhost:3000/node_modules/zone.js/dist/zone.js:216:44)
    at http://localhost:3000/node_modules/zone.js/dist/zone.js:571:58
    at ZoneDelegate.invokeTask (http://localhost:3000/node_modules/zone.js/dist/zone.js:356:38)
    at Object.onInvokeTask (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:9236:45)
    at ZoneDelegate.invokeTask (http://localhost:3000/node_modules/zone.js/dist/zone.js:355:43)
</code></pre>

<p>The error seems to be in FindFormComponent.</p>

<p>FindFormComponent is just the form that has the multiselect (a form to fill out which will then find products).</p>

<p>Here is the relevant html from the FindFormComponent that utilises length:</p>

<pre><code>&lt;div class="row has-error-text"&gt;
    &lt;div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;"&gt;
        &lt;div style="position: relative; display: inline-block; width: 100%;"&gt;
            &lt;multiselect #multiselect&gt;&lt;/multiselect&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;div class="row error-text"  [style.display]="multiselect.selectedCategories.length &lt; 1 &amp;&amp; submitted ? 'block' : 'none'"&gt;
    &lt;div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 form-group input-group btn-group"&gt;
        &lt;small&gt;Please select at least 1 category.&lt;/small&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>