I have this component called multiselect.component and I access one of its html elements (<select id="category-select">)
in the .ts file.
multiselect.component.html:
<select id="category-select" multiple class="form-control"> <option value="1">Meat</option> <option value="2">Dairy</option> <option value="3">Confectionary</option> <option value="4">Dessert</option> <option value="7">Baking</option> <option value="6">Grocers</option> <option value="5">Restaurants</option> <option value="8">Condiments</option> <option value="9">beverages</option> </select> <div class="form-control-icon" id="keywords-icon"></div>
multiselect.component.ts:
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 = []; (<any>$("#category-select")).multiselect({ buttonWidth: '100%', buttonContainer: '<div style="height: 34px;" />', buttonClass: 'none', nonSelectedText: "select categories", nSelectedText: ' categories', allSelectedText: "all categories", selectAllNumber: false, includeSelectAllOption: true, disableIfEmpty: true, onSelectAll: () => { this.allSelected = true; }, onInitialized: () => { }, onChange: (option, checked) => { this.changed(); } }); } changed() { this.selectedCategories = []; var self = this; $('#category-select option:selected').each(function () { self.selectedCategories.push( <any>($(this).text(), $(this).val()) ) }); console.log(this.selectedCategories); if (this.selectedCategories.length < this.numberOfCategories) { this.allSelected = false; } } }
I think that the way I access it is bad practice by using jquery. I think it can be accessed with @viewChild instead.
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):
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: '<div style="height: 34px;" />', buttonClass: 'none', nonSelectedText: "select categories", nSelectedText: ' categories', allSelectedText: "all categories", selectAllNumber: false, includeSelectAllOption: true, disableIfEmpty: true, onSelectAll: () => { this.allSelected = true; }, onInitialized: () => { }, onChange: (option, checked) => { this.changed(); } }); } changed() { this.selectedCategories = []; var self = this; $('#category-select option:selected').each(function () { self.selectedCategories.push( <any>($(this).text(), $(this).val()) ) }); console.log(this.selectedCategories); if (this.selectedCategories.length < this.numberOfCategories) { this.allSelected = false; } } }
I'm getting this console error:
> 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]
Why am I getting that error?
After changing to AfterViewInit, I'm now getting this error:
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)
The error seems to be in FindFormComponent.
FindFormComponent is just the form that has the multiselect (a form to fill out which will then find products).
Here is the relevant html from the FindFormComponent that utilises length:
<div class="row has-error-text"> <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;"> <div style="position: relative; display: inline-block; width: 100%;"> <multiselect #multiselect></multiselect> </div> </div> </div> <div class="row error-text" [style.display]="multiselect.selectedCategories.length < 1 && submitted ? 'block' : 'none'"> <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"> <small>Please select at least 1 category.</small> </div> </div>