angular2属性已更改错误
我有一个指令angular2属性已更改错误,angular,Angular,我有一个指令app.service.ts,用于存储应用程序状态数据,我正尝试从其他组件使用该指令,以便获取和设置应用程序的状态(正在工作) 但是,当我尝试将此指令中的属性绑定到视图时,它会出现此错误 异常:表达式“正在加载:{{loadState}}inApp@0:23'在检查后已更改。上一个值:“false”。[loading:{{loadState}}中的当前值:“true”App@0:23] 这里我试图显示正在加载的文本,此时appState.get().loadState==true 应
app.service.ts
,用于存储应用程序状态数据,我正尝试从其他组件使用该指令,以便获取和设置应用程序的状态(正在工作)
但是,当我尝试将此指令中的属性绑定到视图时,它会出现此错误
异常:表达式“正在加载:{{loadState}}inApp@0:23'在检查后已更改。上一个值:“false”。[loading:{{loadState}}中的当前值:“true”App@0:23]
这里我试图显示正在加载的文本,此时appState.get().loadState==true
应用程序服务.ts-
应用程序ts
import {AppState} from './app.service';
export class App{
constructor(public appState: AppState) {
this.appState.set('loadState', false);
}
get loadState() {
return this.appState.get().loadState;
}
}
export class HomeCmp {
page;
constructor(private wp: WPModels, private appState: AppState) {}
ngOnInit() {
var pageId = this.appState.get().config.home_id;
this.appState.set('loadState', true); // before http request
this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
res => {
this.page = res;
this.appState.set('loadState', false); // after http request
},
err => console.log(err)
);
}
}
export class HomeCmp {
page;
constructor(private wp: WPModels, private appState: AppState) {}
ngOnInit() {
var pageId = this.appState.get().config.home_id;
this.appState.set('loadState', true); // before http request
this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
res => {
this.page = res;
this.appState.set('loadState', false); // after http request
},
err => console.log(err)
);
}
}
export class HomeCmp {
page;
constructor(private wp: WPModels, private service: AppStateService) {}
ngOnInit() {
this.service.updateState(true); // before http request
this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
res => {
this.page = res;
this.service.updateState(false); // after http request
},
err => console.log(err)
);
}
}
app.html
<div class="app-inner">
<p>loading: {{loadState}}</p>
<header></header>
<main layout="column" layout-fill>
<router-outlet></router-outlet>
</main>
</div>
我认为您可以利用ChangeDetectorRef类及其方法detectChanges 为此,将其注入应用程序组件,并在其ngAfterViewInit中调用该方法
constructor(private cdr: ChangeDetectorRef) {}
ngAfterViewInit() {
this.cdr.detectChanges();
}
有关更多详细信息,请参见此问题:
@Injectable()
export class AppStateService {
state: string;
state$: Observable<string>;
private stateObserver : Observer<string>;
constructor(){
this.state$ = new Observable(observer => this.stateObserver = observer).share();
}
updateState(newState) {
this.state = newState;
this.stateObserver.next(newState);
}
}
有关更多详细信息,请参阅以下链接:
您需要再次触发更改检测
wp
似乎以某种方式在Angulars区域之外运行代码。要强制代码返回到Angulars区域,请使用zone.run()
,如下所示。对于更新属性的代码,您的视图绑定到:
从'angular2/core'导入{NgZone};
导出类HomeCmp{
页
构造函数(私有区域:NgZone,私有wp:WPModels,私有appState:appState){}
恩戈尼尼特(){
var pageId=this.appState.get().config.home\u id;
this.appState.set('loadState',true);//在http请求之前
this.wp.fetch(WPEnpoint.Pages,pageId).subscribe(
res=>{
此.zone.run(()=>{
this.page=res;
this.appState.set('loadState',false);//在http请求之后
});
},
err=>console.log(err)
);
}
}
解决方案非常简单,通过制作一个特殊组件来显示state serviceapp.service.ts
中的加载状态,下面是代码:
LoaderCmp直接显示appState服务中的loadState
属性
import {Component} from 'angular2/core';
import {AppState} from "../../app.service";
@Component({
selector: 'loader',
template: `
loading state : {{appState._state.loadState}}
`
})
export class LoaderCmp{
constructor(private appState: AppState) {}
}
import {Component} from 'angular2/core';
import {AppStateService} from "../../app.state";
@Component({
selector: 'loader',
template: `
loading state : {{ active }}
`
})
export class LoaderCmp{
active;
constructor(private service: AppStateService) {}
ngOnInit() {
this.service.state$.subscribe(newState => {
this.active = newState;
});
}
}
app.service.ts保存我们的应用程序状态
import {Injectable} from 'angular2/core';
import {WebpackState} from 'angular2-hmr';
@Injectable()
export class AppState {
_state = {}; // you must set the initial value
constructor(webpackState: WebpackState) {
this._state = webpackState.select('AppState', () => this._state);
}
get(prop?: any) {
return this._state[prop] || this._state;
}
set(prop: string, value: any) {
return this._state[prop] = value;
}
}
app.ts无需配置,只需将LoaderCmp
添加到应用程序指令中即可
@Component({
selector: 'app',
directives: [HeaderCmp, LoaderCmp],
template: `
<div class="app-inner">
<loader></loader>
<header></header>
<main>
<router-outlet></router-outlet>
</main>
</div>
`
})
export class App {
constructor() { }
}
@Component({
selector: 'app',
directives: [HeaderCmp, LoaderCmp],
template: `
<div class="app-inner">
<loader></loader>
<header></header>
<main>
<router-outlet></router-outlet>
</main>
</div>
`
})
export class App {
constructor() { }
}
另一个解决方案是使用observable和share函数,这里我们将
app.service.ts
更改为app.state.ts
,它只支持一个属性
LoaderCmp直接显示appState服务中的loadState
属性
import {Component} from 'angular2/core';
import {AppState} from "../../app.service";
@Component({
selector: 'loader',
template: `
loading state : {{appState._state.loadState}}
`
})
export class LoaderCmp{
constructor(private appState: AppState) {}
}
import {Component} from 'angular2/core';
import {AppStateService} from "../../app.state";
@Component({
selector: 'loader',
template: `
loading state : {{ active }}
`
})
export class LoaderCmp{
active;
constructor(private service: AppStateService) {}
ngOnInit() {
this.service.state$.subscribe(newState => {
this.active = newState;
});
}
}
app.state.ts保存我们的加载状态
import "rxjs/add/operator/share";
import {Observable} from "rxjs/Observable";
import {Observer} from "rxjs/Observer";
import {Injectable} from "angular2/core";
@Injectable()
export class AppStateService {
state: boolean = false;
state$: Observable<boolean>;
private stateObserver : Observer<boolean>;
constructor(){
this.state$ = new Observable(observer => this.stateObserver = observer).share();
}
updateState(newState) {
this.state = newState;
this.stateObserver.next(newState);
}
}
从任何组件更新应用程序状态,例如:home.ts
import {AppState} from './app.service';
export class App{
constructor(public appState: AppState) {
this.appState.set('loadState', false);
}
get loadState() {
return this.appState.get().loadState;
}
}
export class HomeCmp {
page;
constructor(private wp: WPModels, private appState: AppState) {}
ngOnInit() {
var pageId = this.appState.get().config.home_id;
this.appState.set('loadState', true); // before http request
this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
res => {
this.page = res;
this.appState.set('loadState', false); // after http request
},
err => console.log(err)
);
}
}
export class HomeCmp {
page;
constructor(private wp: WPModels, private appState: AppState) {}
ngOnInit() {
var pageId = this.appState.get().config.home_id;
this.appState.set('loadState', true); // before http request
this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
res => {
this.page = res;
this.appState.set('loadState', false); // after http request
},
err => console.log(err)
);
}
}
export class HomeCmp {
page;
constructor(private wp: WPModels, private service: AppStateService) {}
ngOnInit() {
this.service.updateState(true); // before http request
this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
res => {
this.page = res;
this.service.updateState(false); // after http request
},
err => console.log(err)
);
}
}
您可以为此使用共享对象。我认为HTML中的
{{loadState}}
总是以这种方式抛出错误。而是尝试绑定服务中使用的一些共享变量。例如,_state={}是一个共享对象。为它设置一些属性,然后在html中,您可以通过{{appState.\u state.someProperty}}
@micronyks相同的错误我尝试了这个,但它给我的错误完全相同您的意思是您尝试调用检测更改
?在哪个组件生命周期钩子中?否则,我在我的代码片段中输入了一个错误。取而代之的是ngAfterViewInit
…似乎不需要detectChanges
,我喜欢在状态服务中使用observable的想法。但是我选择了普通的app.service.ts,因为它支持多个属性。我写了两种方法的解决方案。