angular - que - ngzone ionic 3
ActualizaciĆ³n de activaciĆ³n de la vista de componente desde el servicio-No hay proveedor para ChangeDetectorRef (3)
Otra opción si desea activar el cambio desde el servicio pero permitir que los componentes controlen si, cuándo y cómo responden, es configurar las suscripciones.
En su servicio, agregue un EventEmitter
:
changeDetectionEmitter: EventEmitter<void> = new EventEmitter<void>();
Cuando ocurre algo en el servicio que puede necesitar activar un ciclo de detección de cambios, simplemente emita:
this.changeDetectionEmitter.emit();
Ahora, en cualquier componente que use este servicio, si necesitan escuchar posibles desencadenantes de cambio, pueden suscribirse y reaccionar adecuadamente:
this.myService.changeDetectionEmitter.subscribe(
() => {
this.cdRef.detectChanges();
},
(err) => {
// handle errors...
}
);
Me gusta este enfoque porque deja el control de la detección de cambios con los componentes a los que pertenece, pero me permite centralizar la lógica en el servicio. El servicio no necesita saber nada acerca de la interfaz de usuario, simplemente notifica a alguien que está escuchando que algo cambió.
Me gustaría actualizar la vista de mi aplicación, activada por eventos del servicio.
Uno de mis servicios inyecta el ChangeDetectorRef. La compilación funciona, pero aparece un error en el navegador cuando la aplicación se reinicia: ¡ No provider for ChangeDetectorRef!
.
Pensé que necesitaba agregarlo a mi AppModule, pero no puedo encontrar ninguna documentación que sugiera que está en un módulo que puedo importar allí. Intenté agregar la clase a la matriz de importación, pero eso causó un error. También recibí un error al intentar agregarlo a la matriz de proveedores en el módulo. Aquí está una versión simplificada de mi servicio:
import {Injectable, ChangeDetectorRef } from ''@angular/core'';
@Injectable()
export class MyService {
private count: number = 0;
constructor(private ref: ChangeDetectorRef){}
increment() {
this.count++;
this.ref.detectChanges();
}
Y el módulo de la aplicación:
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 {}
ACTUALIZAR
Desde entonces he intentado eliminar mi uso de ChangeDetectorRef, y todavía tengo el mismo problema. Supongo que hay algo malo en la forma en que actualicé mi configuración de System JS.
Originalmente creé la aplicación con angular-cli, y estaba intentando actualizar Angular por mi cuenta ya que no habían actualizado eso. Con la versión final de Angular 2.0.0, se ha actualizado angular-cli para usar la última versión de angular. Así que voy a intentar usar sus procedimientos de actualización y espero que eso vaya mejor.
Actualización 2
La actualización webpack / angular-cli salió bien. Tengo la aplicación compilando ahora con Angular 2.0.0 in y angular-cli 1.0.0-beta14. Todavía me sale el mismo error en el navegador. Intenté quitar el ChangeDetectorRef del servicio, pero no lo hice realmente. Lo tuve en dos servicios. Si lo elimino de ambos servicios, entonces mi aplicación se carga bien y funciona bien, excepto cuando intenté usar ChangeDetectorRef . Una vez que lo vuelvo a agregar a uno de los archivos, el navegador se queja de no poder encontrar un proveedor para ello.
Intenté importarlo en mi módulo , pero no es un módulo , por lo que el transpiler se queja. Intenté listarlo como proveedor en mi módulo, pero no tiene una propiedad de provisión, por lo que el transpiler se queja. Problemas similares si intento ponerlo en la matriz de declaraciones .
en las últimas versiones es parte del núcleo ahora, así que solo haga una referencia al núcleo pero use la variable necesaria y debería hacer un truco
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();
});
});
La esperanza ayuda
ChangeDetectorRef
no es una opción para usar aquí. Está buscando cambios en un componente dado y sus hijos.
En su caso, sería mejor utilizar 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();
}
}
He comprobado esta solución con Observables
y funciona sin problemas:
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;
}
}
Y aquí hay un componente que lo usa:
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;
});
}
}