サービスからのイベントによってトリガーされるアプリケーションビューを更新します。
私のサービスの1つがChangeDetectorRefを注入します。コンパイルは機能しますが、アプリのブートストラップ時にブラウザーでエラーが発生します:No provider for ChangeDetectorRef!
。
AppModuleに追加する必要があると思いましたが、そこにインポートできるモジュール内にあることを示唆するドキュメントが見つかりません。クラス自体をインポート配列に追加しようとしましたが、エラーが発生しました。また、モジュール内のプロバイダー配列に追加しようとしてエラーが発生しました。これが私のサービスの簡略版です:
import {Injectable, ChangeDetectorRef } from '@angular/core';
@Injectable()
export class MyService {
private count: number = 0;
constructor(private ref: ChangeDetectorRef){}
increment() {
this.count++;
this.ref.detectChanges();
}
そしてappモジュール:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { MyService } from './my.service';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
providers: [ MyService ],
booststrap: [ AppComponent ]
})
export AppModule {}
[〜#〜] update [〜#〜]
それ以来、ChangeDetectorRefの使用を削除しようとしましたが、まだ同じ問題があります。 System JS configの更新方法に何か問題があると思います。
私はもともとangle-cliでアプリを作成しましたが、Angular=は自分で更新しようとしていました。最終リリースではAngular 2.0.0彼らは、angular-cliを更新して、angularの最新バージョンを使用しているので、アップグレード手順を使用してみますが、うまくいけばうまくいきます。
更新2
Webpack/angular-cliの更新はうまくいきました。 Angular 2.0.0 inとangle-cli 1.0.0-beta14でアプリを構築しています。ブラウザで同じエラーが表示されます。サービスからのChangeDetectorRefが、実際にはそうではありませんでした。2つのサービスに含まれていました。 ChangeDetectorRefを使用しようとしていた場所を除きます。ファイルの1つにそれを追加し直すと、ブラウザは、それのプロバイダー。
私はmoduleでインポートしようとしましたが、moduleではありません、したがって、トランスパイラーは文句を言います。私は自分のモジュールにproviderをリストしようとしましたが、provideプロパティがないため、トランスパイラーは文句を言います。 declarations配列に入れようとすると、同様の問題が発生します。
ChangeDetectorRef
は、ここで使用するオプションではありません。特定のコンポーネントとその子の変更を探しています。
あなたの場合は、ApplicationRef
を使用することをお勧めします。
import {Injectable, ApplicationRef } from '@angular/core';
@Injectable()
export class MyService {
private count: number = 0;
constructor(private ref: ApplicationRef) {}
increment() {
this.count++;
this.ref.tick();
}
}
私はObservables
でこのソリューションをチェックしましたが、問題なく動作します:
import { ApplicationRef, Injectable } from '@angular/core';
import { Observable, ReplaySubject } from "rxjs/Rx";
import * as childProcess from 'child_process';
@Injectable()
export class Reader {
private output: ReplaySubject<string> = new ReplaySubject<string>(0);
constructor(private ref: ApplicationRef) {
var readerProcess = childProcess.spawn('some-process');
readerProcess.stdout.on('data', (data) => {
this.output.next(data.toString());
this.ref.tick();
});
}
public getOutput():Observable<string> {
return this.output;
}
}
そして、これを使用するコンポーネントは次のとおりです。
import {Component} from '@angular/core';
import { ReplaySubject, Observable } from "rxjs/Rx";
import { Reader } from './reader/reader.service';
@Component({
selector: 'app',
template: `
output:
<div>{{output}}</div>
`
})
export class App {
public output: string;
constructor(private reader: Reader) {}
ngOnInit () {
this.reader.getOutput().subscribe((val : string) => {
this.output = val;
});
}
}
サービスから変更をトリガーするが、コンポーネントが応答するかどうか、タイミング、および方法を制御できるようにする場合の別のオプションは、サブスクリプションを設定することです。
サービスにEventEmitter
を追加します。
changeDetectionEmitter: EventEmitter<void> = new EventEmitter<void>();
変更検出サイクルをトリガーする必要がある可能性のある何かがサービスで発生した場合、単純に以下を発行します。
this.changeDetectionEmitter.emit();
現在、このサービスを使用するコンポーネントでは、可能な変更トリガーをリッスンする必要がある場合、サブスクライブして適切に対応できます。
this.myService.changeDetectionEmitter.subscribe(
() => {
this.cdRef.detectChanges();
},
(err) => {
// handle errors...
}
);
私はこのアプローチが好きです。なぜなら、それが属するコンポーネントで変更検出の制御を残しますが、サービスのロジックを集中化できるからです。サービスはUIについて何も知る必要はありません。何かが変更されたことを聞いている人に通知するだけです。
現在、最新バージョンではコアの一部であるため、コアへの参照を作成しますが、必要な変数を使用してトリックを行う必要があります
import { TestBed } from '@angular/core/testing';
import { ChangeDetectorRef } from '@angular/core';
import { MyService } from './my.service';
describe('MyService', () => {
beforeEach(() => TestBed.configureTestingModule({
providers: [ChangeDetectorRef] // <--- LOOK AT ME I'M A PROVIDER!
}));
it('should be created', () => {
const service: MyService = TestBed.get(MyService);
expect(service).toBeTruthy();
});
});
希望は助けます
私はこれには長い間遅れていることを知っていますが、呼び出される関数を介してChangeDetectorRefをサービスに渡すだけでした。
//myservice
import { Injectable, ChangeDetectorRef } from '@angular/core';
@Injectable()
export class MyService {
constructor(){}
increment(ref: ChangeDetectorRef, output: number) {
output++;
ref.detectChanges();
}
コンポーネント
import {Component} from '@angular/core';
import { MyService } from './myservice.service';
@Component({
selector: 'app',
template: `
output:
<div>{{output}}</div>
`
})
export class App {
public output: number;
constructor(public ref: ChangeDetectorRef, private myService: MyService) {}
ngOnInit () {
this.myService.increment(this.ref,output)
}
}