Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular2表达式已更改为Territhasbeenschecked错误_Angular_Angular2 Services - Fatal编程技术网

Angular2表达式已更改为Territhasbeenschecked错误

Angular2表达式已更改为Territhasbeenschecked错误,angular,angular2-services,Angular,Angular2 Services,我已经阅读了关于这个错误的文档,我想我理解为什么会出现这个问题。我在试图找到一种适合我的替代体系结构时遇到了一个问题 我的站点的根组件(app.component)上有一个“加载”组件。它是一个第三方组件(ngx加载),基本上会抛出一个加载指示器,向用户显示应用程序中正在发生的事情,这需要一点时间。加载组件接受一个参数,该参数告诉它是否显示: <ngx-loading [show]="loading" [config]="{ backdropBorderRadius: '14px' }"&

我已经阅读了关于这个错误的文档,我想我理解为什么会出现这个问题。我在试图找到一种适合我的替代体系结构时遇到了一个问题

我的站点的根组件(app.component)上有一个“加载”组件。它是一个第三方组件(ngx加载),基本上会抛出一个加载指示器,向用户显示应用程序中正在发生的事情,这需要一点时间。加载组件接受一个参数,该参数告诉它是否显示:

<ngx-loading [show]="loading" [config]="{ backdropBorderRadius: '14px' }"></ngx-loading>
这一切的好处在于,我可以在我的应用程序中的任何地方更改站点服务值,并控制是否弹出加载指示器。糟糕的是,现在我看到了这个表达式的变化,即TerithasBeenCheckedError错误

再一次,我想我理解了错误发生的原因,但是到目前为止我看到的解决方案不允许我继续使用这个简单的组件来处理所有的“加载”调用。还是我遗漏了什么

网站服务:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject }    from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class SiteService {

  private currentRoute = new Subject<string>();
  private currentAction = new Subject<string>();

  private loading = new BehaviorSubject<boolean>(false);

  constructor() {
  }

  public menuState:string = 'in';
  toggleMenuPicker() {
    this.menuState = this.menuState === 'out' ? 'in' : 'out';
  }

  getCurrentRoute(): Observable<string> {
    return this.currentRoute.asObservable();
  }
  setCurrentRoute(route: string) {
    this.currentRoute.next(route);    
  }

  getCurrentAction(): Observable<string> {
    return this.currentAction.asObservable();
  }
  setCurrentAction(action: string) {
    this.currentAction.next(action);
  }

  getLoading(): Observable<boolean> {
    return this.loading.asObservable();
  }

  setLoading(show: boolean) {
    this.loading.next(show);
  }



}
从'@angular/core'导入{Injectable};
从“rxjs/Observable”导入{Observable};
从'rxjs/Subject'导入{Subject};
从'rxjs/BehaviorSubject'导入{BehaviorSubject};
@可注射()
导出类站点服务{
private currentRoute=新主题();
private currentAction=新主题();
私有加载=新行为主体(false);
构造函数(){
}
public menuState:string='in';
toggleMenuPicker(){
this.menuState=this.menuState=='out'?'in':'out';
}
getCurrentRoute():可观察{
返回此.currentRoute.asObservable();
}
setCurrentRoute(路由:字符串){
this.currentRoute.next(路由);
}
getCurrentAction():可观察{
返回此.currentAction.asObservable();
}
setCurrentAction(操作:字符串){
this.currentAction.next(动作);
}
getLoading():可观察{
返回此.loading.asObservable();
}
设置加载(显示:布尔值){
这个。加载。下一个(显示);
}
}
应用程序组件

import { Component, OnDestroy, AfterContentInit } from '@angular/core';
import { trigger, state, style, transition, animate} from '@angular/animations';
import { SiteService } from './site/site.service';
import 'rxjs/add/operator/takeUntil';
import { Subject } from 'rxjs/Subject';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations: [
    trigger('menuState', [
      state('in', style({
        transform: 'translate3d(-100%, 0, 0)'
      })),
      state('out', style({
        transform: 'translate3d(0, 0, 0)'
      })),
      transition('in => out', animate('200ms ease-in-out')),
      transition('out => in', animate('200ms ease-in-out'))
    ])
  ]
})
export class AppComponent implements OnDestroy, AfterContentInit {
  private ngUnsubscribe: Subject<void> = new Subject<void>();

 public loading;

  constructor(public siteService: SiteService) {
  }

  ngAfterContentInit() {
    this.siteService.getLoading().takeUntil(this.ngUnsubscribe).subscribe(res => {this.loading = res})
  }

  ngOnDestroy() {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }



}
从'@angular/core'导入{Component,OnDestroy,AfterContentInit};
从“@angular/animations”导入{触发器、状态、样式、转换、动画};
从“./site/site.service”导入{SiteService};
导入'rxjs/add/operator/takeUntil';
从'rxjs/Subject'导入{Subject};
@组成部分({
选择器:'应用程序根',
templateUrl:“./app.component.html”,
样式URL:['./app.component.css'],
动画:[
触发器('menuState'[
状态('in',风格)({
转换:“translate3d(-100%,0,0)”
})),
状态('out',风格({
转换:“translate3d(0,0,0)”
})),
过渡('in=>out',动画('200ms缓进-缓出'),
过渡('out=>in',动画('200ms缓进-缓出'))
])
]
})
导出类AppComponent实现OnDestroy,AfterContentInit{
private ngUnsubscribe:Subject=new Subject();
公共装载;
构造函数(公共站点服务:站点服务){
}
ngAfterContentInit(){
this.siteService.getLoading().takeUntil(this.ngUnsubscribe.subscribe)(res=>{this.loading=res})
}
恩贡德斯特罗(){
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
尝试强制

this.siteService.getLoading()
.takeUntil(this.ngUnsubscribe)
.订阅(res=>{
这个。加载=res;

this.ref.detectChanges();//您可以使用changedtectionstrategy.OnPush或changedtectorref.detach()保留单个组件,同时避免错误

以下是一种可能的解决方案:

@Component({
  selector: 'loader',
  template: `<ngx-loading [show]="loading"></ngx-loading>`
})
export class LoaderComponent {
 public loading;

 constructor(public siteService: SiteService, private changeDetectorRef: ChangeDetectorRef) {
   this.changeDetectorRef.detach();
   this.siteService.getLoading()
                   .takeUntil(this.ngUnsubscribe)
                   .subscribe(res => {
                                this.loading = res;
                                this.changeDetectorRef.detectChanges();
                    });       
  }
}
@组件({
选择器:“加载程序”,
模板:``
})
导出类装入器组件{
公共装载;
构造函数(公共siteService:siteService,私有changeDetectorRef:changeDetectorRef){
this.changeDetectorRef.detach();
this.siteService.getLoading()
.takeUntil(this.ngUnsubscribe)
.订阅(res=>{
这个。加载=res;
this.changeDetectorRef.detectChanges();
});       
}
}

您可以创建此组件并在AppComponent模板中使用它。

我可能最终会这样做,但老实说,这似乎是一个黑客行为。我从中了解到:。特别是,他说“Angular也将对所有子组件运行更改检测”.考虑到这是我的顶级组件,这不意味着我会放慢速度吗?如果你能向我解释一下为什么在这种情况下它没问题,或者为什么我过于担心会导致应用程序出现一个全新的更改检测周期,我会接受。你看到了什么解决方案?我也有同样的问题->非常渴望找到解决方案。我很高兴使用带有DIV的自定义加载屏幕,该DIV在*ngIf参数切换为true时显示。阅读本文以了解原因和可能的修复方法您会看到我在下面的响应中引用了该文章-我已经阅读了。您能告诉我该文章中该问题解决方案的具体位置吗?我无法回答o找到它。相关问题:
ChangeDetectionStrategy.OnPush
将只运行一次更改检测,忽略同一个VM Turns的任何新的可能的模型更改。当我们使用可观察时,我们应该使用OnPush策略并调用ChangeDetectorRef.detectChanges()或ChangeDetectorRef.markForCheck()。
this.siteService.getLoading()
                .takeUntil(this.ngUnsubscribe)
                .subscribe(res => {
                  this.loading = res;
                  this.ref.detectChanges(); // <-- force change detection
                });
@Component({
  selector: 'loader',
  template: `<ngx-loading [show]="loading"></ngx-loading>`
})
export class LoaderComponent {
 public loading;

 constructor(public siteService: SiteService, private changeDetectorRef: ChangeDetectorRef) {
   this.changeDetectorRef.detach();
   this.siteService.getLoading()
                   .takeUntil(this.ngUnsubscribe)
                   .subscribe(res => {
                                this.loading = res;
                                this.changeDetectorRef.detectChanges();
                    });       
  }
}