Представление Angular 2 не работает - невозможно прочитать свойство nativeElement из undefined
У меня есть этот компонент с именем multiselect.component, и я получаю доступ к одному из его элементов HTML(<select id="category-select">)
в файле .ts.
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;
}
}
}
Я думаю, что способ, которым я получаю к нему доступ, является плохой практикой при использовании jquery. Я думаю, что к нему можно получить доступ с помощью @viewChild.
Поэтому я пытаюсь изменить его следующим образом (сначала я просто избавляюсь от первого средства доступа к элементу jquery, а потом сделаю все остальное):
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;
}
}
}
Я получаю эту ошибку консоли:
> 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]
Почему я получаю эту ошибку?
После перехода в AfterViewInit я получаю эту ошибку:
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)
Ошибка, кажется, в FindFormComponent.
FindFormComponent - это просто форма с множественным выбором (форма для заполнения, которая затем найдет продукты).
Вот соответствующий HTML-код из FindFormComponent, который использует длину:
<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>