在我的angular 4应用程序中,每次我的侧边栏组件呈现时,我都会收到这个奇怪的错误。我没有任何属性" name"在我的代码中。发现很难弄清楚错误被抛出的原因。以下是控制台错误日志。任何帮助深表感谢。
html代码:
<div class="sidebar" >
<app-sidebar></app-sidebar>
<div class="sidebar-background" style="background-image: url(assets/img/sidebar-1.jpg)"></div>
</div>
错误日志:
ERROR TypeError: Cannot read property 'name' of undefined
at checkBindingNoChanges (core.js:9912)
at checkNoChangesNodeInline (core.js:13961)
at checkNoChangesNode (core.js:13935)
at debugCheckNoChangesNode (core.js:14764)
at debugCheckDirectivesFn (core.js:14666)
at Object.eval [as updateDirectives] (AppComponent.html:2)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:14648)
at checkNoChangesView (core.js:13773)
at callViewAction (core.js:14126)
at execComponentViewsAction (core.js:14078)
at checkNoChangesView (core.js:13776)
at callWithDebugContext (core.js:15049)
at Object.debugCheckNoChangesView [as checkNoChangesView] (core.js:14593)
at ViewRef_.webpackJsonp.../../../core/esm5/core.js.ViewRef_.checkNoChanges (core.js:11584)
at core.js:5903
View_AppComponent_0 @ AppComponent.html:2
proxyClass @ compiler.js:14645
webpackJsonp.../../../core/esm5/core.js.DebugContext_.logError @ core.js:14989
webpackJsonp.../../../core/esm5/core.js.ErrorHandler.handleError @ core.js:1501
(anonymous) @ core.js:5908
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:365
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run @ zone.js:125
webpackJsonp.../../../core/esm5/core.js.NgZone.runOutsideAngular @ core.js:4681
webpackJsonp.../../../core/esm5/core.js.ApplicationRef.tick @ core.js:5908
(anonymous) @ core.js:5734
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:365
onInvoke @ core.js:4733
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:364
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run @ zone.js:125
webpackJsonp.../../../core/esm5/core.js.NgZone.run @ core.js:4550
next @ core.js:5734
schedulerFn @ core.js:4319
webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:239
webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.next @ Subscriber.js:186
webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber._next @ Subscriber.js:126
webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next @ Subscriber.js:90
webpackJsonp.../../../../rxjs/Subject.js.Subject.next @ Subject.js:55
webpackJsonp.../../../core/esm5/core.js.EventEmitter.emit @ core.js:4299
checkStable @ core.js:4698
onHasTask @ core.js:4746
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.hasTask @ zone.js:418
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate._updateTaskCount @ zone.js:438
webpackJsonp.../../../../zone.js/dist/zone.js.Zone._updateTaskCount @ zone.js:262
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:182
drainMicroTaskQueue @ zone.js:593
Promise resolved (async)
scheduleQueueDrain @ zone.js:552
scheduleMicroTask @ zone.js:560
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:387
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:209
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleMicroTask @ zone.js:229
scheduleResolveOrReject @ zone.js:758
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneAwarePromise.then @ zone.js:847
webpackJsonp.../../../core/esm5/core.js.PlatformRef.bootstrapModule @ core.js:5562
../../../../../src/main.ts @ main.ts:11
__webpack_require__ @ bootstrap 655e16dd1fe7443b4474:54
0 @ main.bundle.js:1835
__webpack_require__ @ bootstrap 655e16dd1fe7443b4474:54
webpackJsonpCallback @ bootstrap 655e16dd1fe7443b4474:25
(anonymous) @ main.bundle.js:1
AppComponent.html:2 ERROR CONTEXT
完成TS:
import { Component, OnInit } from '@angular/core';
import { LabelsModel } from './../../core/models/labels';
import { LevelModel } from './../../core/models/level';
import { DataService } from './../../core/service/data.service';
import * as _ from 'underscore';
import { AppService } from './../../core/service/app.service';
import { CategoryModel } from './../../core/models/cat';
import { OnDestroy } from '@angular/core/src/metadata/lifecycle_hooks';
import { AttributeModel } from './../../core/models/att';
import { CountModel, CountChildModel } from './../../core/models/count';
import { SearchModel } from './../../core/models/search';
declare const $: any;
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
menuItems: any[];
highlightedDiv: number;
productCategory: CategoryModel[];
productCategoryM: CategoryModel[];
productFiltered: AttributeModel[];
searchOrder = [];
productAttribute: AttributeModel[];
productAttributeM: AttributeModel[];
countModel: CountModel[];
countChildModel: Array<CountChildModel> = [];
countVal: any;
data = [];
searchArray = [];
searchModel: SearchModel = {};
childSearch: string[] = [];
productSelected: LevelModel;
searchCheck: SearchModel[];
checkB: boolean;
searchCheck1: SearchModel;
// productName: string;
filterSelected: boolean;
labelList: LabelsModel[] = [];
constructor(private _AppService: AppService, private _dataService: DataService) { }
ngOnInit() {
this._AppService.getData().subscribe(te => this.labelList = te);
this._dataService.productSelectedName.subscribe(product => this.productChange(product));
this._dataService.toggleValue.subscribe(toggleVal => this.changeToggle(toggleVal));
this._AppService.getCat$().subscribe(categoryValues => this.processCategory(categoryValues));
this._dataService.filterList.subscribe(filterValue => this.changeFilter(filterValue));
this._dataService.setFilterSelected(false);
this._dataService.filterSelect.subscribe(val => this.filterSelected = val);
}
isMobileMenu() {
if ($(window).width() > 991) {
return false;
} else {
return true;
}
};
changeToggle(toggle): void {
this.highlightedDiv = toggle;
}
clearFilters() {
this._dataService.setFilterList([]);
this._dataService.setFilterSelected(false);
this._dataService.setDisplay(0);
}
productChange(product) {
this.productSelected = {};
if (product === undefined || product == null) {
this.productSelected.level = 'level1';
this.productSelected.product = 'root';
} else {
this.productSelected = product;
}
if (this.productCategoryM !== undefined) {
this.processCategory(this.productCategoryM);
}
}
processCategory(categoryValues): void {
this.searchOrder = [];
this.productCategory = _.where(categoryValues, { id: this.productSelected.product });
this.productCategoryM = categoryValues;
for (const search of this.productCategory[0].search) {
this.searchOrder.push(search);
}
this._AppService.getAtt$().subscribe(attributeValues => this.processAttribute(attributeValues));
}
processAttribute(attributeValues): void {
const searchObj = {};
let filters = [];
this.productFiltered = [];
this.productAttributeM = attributeValues;
this.searchCheck = this._dataService.getFilterList();
searchObj[this.productSelected.level] = this.productSelected.product;
const searchKey = this.productSelected.level;
this.productAttribute = _.where(attributeValues, searchObj);
if (this._dataService.getFilterSelected() == true) {
filters = this._dataService.getFilterList();
for (let i = 0; i < filters.length; i++) {
for (let j = 0; j < filters[i].searchChild.length; j++) {
if (isNaN(+filters[i].searchChild[j])) {
searchObj[filters[i].searchParent] = filters[i].searchChild[j];
} else {
searchObj[filters[i].searchParent] = +filters[i].searchChild[j];
}
}
}
this.productFiltered.push.apply(this.productFiltered, (_.where(this.productAttribute, searchObj)));
this.productAttribute = _.unique(this.productFiltered);
}
this.countModel = [];
for (let i = 0; i < this.searchOrder.length; i++) {
this.checkB = false;
if (this.searchCheck !== undefined && this.searchCheck.length > 0) {
this.searchCheck1 = this.searchCheck.find(this.check, this.searchOrder[i]);
if (this.searchCheck1 !== undefined) {
if (this.searchCheck1.searchChild.length > 0) {
this.checkB = true;
}
}
}
this.countModel[i] = {};
this.countModel[i].parentName = this.searchOrder[i];
this.countVal = _.pairs(_.countBy(this.productAttribute, this.searchOrder[i]));
this.countChildModel = [];
for (let j = 0; j < this.countVal.length; j++) {
if (this.countVal[j][0] !== 'null'){
this.countChildModel[j] = {};
this.countChildModel[j].childName = this.countVal[j][0];
this.countChildModel[j].count = this.countVal[j][1];
if (this.checkB) {
if ((this.searchCheck.find(this.check, this.searchOrder[i]).searchChild.find
(this.check1, this.countVal[j][0])) !== undefined) {
this.countChildModel[j].check = true;
}
}
}
}
this.countModel[i].child = _.sortBy(this.countChildModel, 'childName');
}
for (let i = 0; i < this.countModel.length; i++) {
this.countModel[i].parentLabel = _.where(this.labelList, { id: this.countModel[i].parentName })[0].label;
}
}
check(ad) {
return ad.searchParent == this ? true : false;
}
check1(ad2) {
return ad2 == this ? true : false;
}
changeFilter(val) {
val.length == 0 ? this._dataService.setFilterSelected(false) : this._dataService.setFilterSelected(true);
this.processAttribute(this.productAttributeM);
}
taxonSelected(parent, taxon, checked) {
this.searchModel = {};
this.childSearch = [];
this.searchArray = [];
if (checked) {
this.searchArray = this._dataService.getFilterList();
if (_.where(this._dataService.getFilterList(), { searchParent: parent }).length > 0) {
this.childSearch = _.where(this._dataService.getFilterList(), { searchParent: parent })[0].searchChild;
this.searchArray.splice((this.searchArray.map(function (d) { return d['searchParent']; }).indexOf(parent)), 1);
this.childSearch.push(taxon.childName);
this.searchModel.searchChild = this.childSearch;
this.searchArray.push(this.searchModel);
this.searchModel.searchParent = parent;
this._dataService.setFilterList(this.searchArray);
} else {
this.childSearch.push(taxon.childName);
this.searchModel.searchChild = this.childSearch;
this.searchModel.searchParent = parent;
this.searchArray.push(this.searchModel);
this._dataService.setFilterList(this.searchArray);
}
} else {
this.childSearch = _.where(this._dataService.getFilterList(), { searchParent: parent })[0].searchChild;
if (this._dataService.getFilterList().length > 1) {
this.searchArray = this._dataService.getFilterList();
this.searchArray.splice((this.searchArray.map(function (d) { return d['searchParent']; }).indexOf(parent)), 1);
if (this.childSearch.length > 1) {
this.childSearch.splice(this.childSearch.indexOf(taxon.childName), 1);
this.searchModel.searchChild = this.childSearch;
this.searchModel.searchParent = parent;
this.searchArray.push(this.searchModel);
this._dataService.setFilterList(this.searchArray);
} else {
this._dataService.setFilterList(this.searchArray);
}
} else {
if (this.childSearch.length > 1) {
this.childSearch.splice(this.childSearch.indexOf(taxon.childName), 1);
this.searchModel.searchChild = this.childSearch;
this.searchModel.searchParent = parent;
this.searchArray.push(this.searchModel);
this._dataService.setFilterList(this.searchArray);
} else {
this._dataService.setFilterList([]);
}
}
}
}
ngOnDestroy(): void {
}
}
完整的side.html代码:
<div class="logo">
<a href="" class="simple-text">
<div class="logo-img">
<img src="" />
</div>
Tenets Technologies
</a>
</div>
<div class="sidebar-wrapper scrollbar-danger" >
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6 refine ">
<h6>Refine </h6>
</div>
<div class="col-lg-5 col-md-5 col-sm-5 clear text-right" (click) = "clearFilters()" *ngIf="filterSelected==true">
Clear All
<i class="material-icons">clear</i>
</div>
</div>
<div class="nav-container ">
<ul class="nav ">
<li routerlinkactive="active" *ngFor="let search of countModel" class="">
<a data-toggle="collapse" href="#{{search.parentName}}" class="">
<div class="row">
<div class="col-md-2 col-sm-2 col-xs-2 ">
<i class="material-icons">apps</i>
</div>
<div class="col-xs-8 col-sm-8 col-md-8">
<p class="test"> {{search.parentLabel}}</p>
</div>
<div class="col-md-2 col-sm-2 col-xs-2 ">
<b class="caret"></b>
</div>
</div>
</a>
<div class="collapse listCont scrollbar-danger" id="{{search.parentName}}">
<ul class="nav child">
<li routerlinkactive="active" *ngFor="let test of search.child">
<div class="checkbox">
<label>
<input type="checkbox" name="optionsCheckboxes" [checked]="test.check" (click)="taxonSelected(search.parentName,test, $event.target.checked)">
<span class="checkbox-label">
{{test.childName}} ({{test.count}})
</span>
</label>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
App.component.ts
import { Component, OnInit, ViewChild, AfterViewInit, ChangeDetectorRef } from '@angular/core';
import { Location, LocationStrategy, PathLocationStrategy, PopStateEvent } from '@angular/common';
import 'rxjs/add/operator/filter';
import { NavbarComponent } from './components/navbar/navbar.component';
import { Router, NavigationEnd, NavigationStart } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
import PerfectScrollbar from 'perfect-scrollbar';
import { DataService } from 'app/core/service/data.service';
import { MatSnackBar } from '@angular/material';
import { AppService } from 'app/core/service/app.service';
declare const $: any;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private _router: Subscription;
private lastPoppedUrl: string;
private yScrollStack: number[] = [];
/* headerValue = 0; */
toggleSide: number;
@ViewChild(NavbarComponent) navbar: NavbarComponent;
constructor(public location: Location, private router: Router,
private _dataService: DataService, private cdr: ChangeDetectorRef,private _AppService:AppService
) { }
ngOnInit() {
$.material.init();
this._dataService.toggleValue.subscribe(toggle => this.changeToggle(toggle));
const elemMainPanel = <HTMLElement>document.querySelector('.main-panel');
const elemSidebar = <HTMLElement>document.querySelector('.sidebar .sidebar-wrapper');
this._dataService.setDisplay(0);
/* this.headerValue = 0;
this._dataService.headerValue.subscribe(header => this.headerValue = header); */
this.location.subscribe((ev: PopStateEvent) => {
this.lastPoppedUrl = ev.url;
});
this.router.events.subscribe((event: any) => {
this.navbar.sidebarClose();
if (event instanceof NavigationStart) {
if (event.url != this.lastPoppedUrl)
this.yScrollStack.push(window.scrollY);
} else if (event instanceof NavigationEnd) {
if (event.url == this.lastPoppedUrl) {
this.lastPoppedUrl = undefined;
window.scrollTo(0, this.yScrollStack.pop());
} else
window.scrollTo(0, 0);
}
});
this._router = this.router.events.filter(event => event instanceof NavigationEnd).subscribe((event: NavigationEnd) => {
elemMainPanel.scrollTop = 0;
elemSidebar.scrollTop = 0;
});
if (window.matchMedia(`(min-width: 960px)`).matches && !this.isMac()) {
let ps = new PerfectScrollbar(elemMainPanel);
ps = new PerfectScrollbar(elemSidebar);
}
}
changeToggle(val) {
this.toggleSide = val;
this.isDetailsMenu();
}
isDetailsMenu() {
if (this.toggleSide == 1) {
return false;
} else {
return true;
}
}
ngAfterViewInit() {
this.runOnRouteChange();
}
runOnRouteChange(): void {
if (window.matchMedia(`(min-width: 960px)`).matches && !this.isMac()) {
const elemMainPanel = <HTMLElement>document.querySelector('.main-panel');
const ps = new PerfectScrollbar(elemMainPanel);
ps.update();
}
}
isMac(): boolean {
let bool = false;
if (navigator.platform.toUpperCase().indexOf('MAC') >= 0 || navigator.platform.toUpperCase().indexOf('IPAD') >= 0) {
bool = true;
}
return bool;
}
}
App.component.html
<div class="wrapper">
<div class="sidebar" >
<app-sidebar></app-sidebar>
<div class="sidebar-background" style="background-image: url(assets/img/sidebar-1.jpg)"></div>
</div>
<div class="main-panel" [ngClass]="{'dtl1': isDetailsMenu()}">
<app-navbar class="pos" [ngClass]="{'dtl-nav': isDetailsMenu()}"></app-navbar>
<app-app-filter ></app-app-filter>
<app-tree></app-tree>
<router-outlet></router-outlet>
<app-footer></app-footer>
</div>
</div>
答案 0 :(得分:14)
我刚刚得到了这个问题,似乎错误本身就是一个红色的鲱鱼,因为错误是角度的错误,请检查以下问题以获取更多内容
实际的潜在错误很可能是expressionChangedAfterItHasBeenCheckedError
。在开发模式下,angular会超过绑定两次,第二次检查它们是否具有相同的值。如果它们没有相同的值,则假定读取值修改了那些绑定并因此抛出expressionChangedAfterItHasBeenCheckedError
- 该异常的其他来源可能是如果您有非常不稳定的值,这些值经常变化,请尝试删除绑定,而不是错误应该消失,而不是你确定它是expressionChangedAfterItHasBeenCheckedError
长话短说,不关心您发布的例外情况,尝试解决expressionChangedAfterItHasBeenCheckedError
(谷歌如何发生并得到解决 - 有很多问题已经在SO上发布了)
答案 1 :(得分:0)
您的方法isDetailsMenu()
必须包含一个试图使用自己的name
属性的变量。
在做某事之前,您应该始终测试变量。
isDetailsMenu() {
return this.myVar && this.myVar.name === 'dtl';
}