서비스에서 구성 요소 보기 업데이트 트리거 - ChangeDetectorRef에 대한 공급자 없음
서비스의 이벤트로 인해 트리거된 응용프로그램 보기를 다시 업데이트하고 싶습니다.
내 서비스 중 하나가 ChangeDetectorRef를 주입합니다.합니다.합니다.No provider for ChangeDetectorRef!
.
앱 모듈에 추가해야 한다고 생각했는데 거기서 가져올 수 있는 모듈에 있다는 문서를 찾을 수 없습니다.클래스 자체를 Import Array에 추가하려고 했는데 오류가 발생했습니다.모듈의 공급자 배열에 추가하는 중에도 오류가 발생했습니다.다음은 제 서비스의 단순화 버전입니다.
import {Injectable, ChangeDetectorRef } from '@angular/core';
@Injectable()
export class MyService {
private count: number = 0;
constructor(private ref: ChangeDetectorRef){}
increment() {
this.count++;
this.ref.detectChanges();
}
그리고 앱 모듈:
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 {}
갱신하다
그 이후로 ChangeDetectorRef 사용을 제거하려고 했지만 여전히 같은 문제가 있습니다.System JS config를 업데이트한 방법이 잘못된 것 같습니다.
저는 원래 angular-cli로 앱을 만들었고, 그들이 업데이트를 하지 않았기 때문에 angular를 스스로 업데이트하려고 했습니다.Angular 2.0.0의 최종 릴리스를 통해 Angular-cli를 최신 버전의 Angular를 사용하도록 업데이트했습니다.그래서 저는 그들의 업그레이드 절차를 사용해 볼 것이고 그것이 더 잘 되기를 바랍니다.
업데이트2
웹팩/angular-cli 업데이트가 잘 되었습니다.나는 지금 Angular 2.0.0 in과 Angular-cli 1.0.0-beta14로 앱 빌드를 가지고 있습니다.브라우저에 여전히 같은 오류가 발생합니다.서비스에서 ChangeDetectorRef를 제거하려고 했지만 실제로 제거하지 못했습니다.저는 두 가지 서비스를 받았습니다.두 서비스에서 제거하면 ChangeDetectorRef를 사용하려고 했던 부분을 제외하고는 앱이 잘 로드되고 잘 작동합니다.파일 중 하나에 다시 추가하면 브라우저에서 제공자를 찾을 수 없다는 불만이 제기됩니다.
제 모듈로 수입하려고 했는데 모듈이 아니라서 트랜스필러가 불만을 제기합니다.모듈에 공급자를 등록하려고 했는데 공급자 속성이 없어서 트랜스필러가 불만을 제기합니다.선언 배열에 넣으려고 하면 비슷한 문제가 발생합니다.
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에 대해 아무것도 알 필요가 없으며, 듣고 있는 사람에게 무언가 바뀌었다는 것을 알리는 것뿐입니다.
이미 오래 전에 이 문제를 해결해야 한다는 것을 알고 있지만, 단순히 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)
}
}
최신 버전은 이제 코어의 일부이므로 코어에 대한 참조만 가능하지만 필요한 변수를 사용하고 트릭을 수행해야 합니다.
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();
});
});
희망은 도움이 됩니다.
사용방법ApplicationRef
좋은 해결책입니다.몇 가지 해결책이 더 있습니다.
사용.
setTimeout
@Injectable() export class MyService { private count: number = 0; constructor(){} increment() { setTimeout(() => this.count++, 0); } }
사용.
Promise
@Injectable() export class MyService { private count: number = 0; constructor(){} increment() { Promise.resolve().then(() => this.count++); } }
변경 탐지에 Zone.js를 사용하는 경우 두 솔루션 모두 Angular가 변경 탐지를 트리거하도록 강제합니다. 이것이 기본 방식이며 앱의 99%가 이를 사용합니다.
서비스를 구성 요소 수준의 공급업체에 추가해야 합니다.
@Component({
// ...
providers: [MyService]
})
export class SomeComponent {
// ...
}
언급URL : https://stackoverflow.com/questions/39511820/trigger-update-of-component-view-from-service-no-provider-for-changedetectorre
'programing' 카테고리의 다른 글
코드를 정리하는 가장 좋은 명령줄 도구는 무엇입니까? (0) | 2023.10.05 |
---|---|
프로그래밍 방식으로 배송 방법 설정 우커머스 (0) | 2023.10.05 |
MySQL에서 스키마 이름을 변경하는 방법 (0) | 2023.10.05 |
파워셸 ps1 파일은 "cmdlet, 함수, 작동 가능한 프로그램 또는 스크립트 파일로 인식되지 않습니다." (0) | 2023.10.05 |
정지된 도커 컨테이너만 나열합니다. (0) | 2023.10.05 |