[英]How to force update the dependency injection component in Angular: NullInjectorError: No provider for ChangeDetectorRef
我有兩個UI組件,
Tab3Page:保存數據
Tab2Page:加載數據
Tab2Page已注入到Tab3Page
我試圖通過Tabd3Page保存數據時自動在Tab2Page中加載數據。
當前,當我將數據保存到tab3中時,除非手動刷新頁面瀏覽器,否則tab2不會自動更新。 有沒有一種方法可以像在setSate()中一樣強制渲染頁面
以下是組件Tab3Page
@Component({
selector: 'app-tab3',
templateUrl: 'tab3.page.html',
styleUrls: ['tab3.page.scss']
})
export class Tab3Page implements OnInit {
pics: Picture[] = [];
constructor(public fileservice: FileService, private tab2: Tab2Page) {}
ngOnInit() {
console.log('ng init');
this.pics = PICS;
}
saveContent(pic: Picture) {
this.fileservice.savefile(pic);
this.tab2.updatePics();
this.tab2.refreshComponent();
}
}
以下是組件Tab2Page
@Component({
selector: 'app-tab2',
templateUrl: 'tab2.page.html',
styleUrls: ['tab2.page.scss']
})
export class Tab2Page implements
OnInit,
OnChanges {
@Input() pics: Picture[];
constructor(public fileservice:FileService, private cdr: ChangeDetectorRef) { }
// constructor(public fileservice: FileService) { }
ngOnInit() {
console.log('ng init');
this.updatePics();
}
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
console.log('changes', changes);
}
async updatePics() {
this.pics = await this.fileservice.getSavedPics();
}
refreshComponent() {
this.cdr.detectChanges();
console.log('component refresh triggred');
}
}
數據通過組件Tab2Page中的pics變量按以下方式綁定到HTML中
<ion-list *ngFor="let pic of pics">
<ion-item-sliding>
<ion-item>
<ion-grid>
<ion-row>
<ion-col size="3">
<ion-thumbnail>
<img [src]="(pic.url | safeurl)">
</ion-thumbnail>
</ion-col>
<ion-col size="9">
<ion-label>{{pic.name}}</ion-label>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
<ion-item-options side="end">
<ion-item-option>Delete</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
** UPDATE嘗試使用ChangeDetectorRef應用建議的解決方案但是,盡管編譯成功,但在瀏覽器事件中出現以下錯誤。
core.js:9110 ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[IonItemOption -> ChangeDetectorRef]:
StaticInjectorError(Platform: core)[IonItemOption -> ChangeDetectorRef]:
NullInjectorError: No provider for ChangeDetectorRef!
NullInjectorError: StaticInjectorError(AppModule)[IonItemOption -> ChangeDetectorRef]:
StaticInjectorError(Platform: core)[IonItemOption -> ChangeDetectorRef]:
NullInjectorError: No provider for ChangeDetectorRef!
at NullInjector.get (core.js:778)
at resolveToken (core.js:2564)
at tryResolveToken (core.js:2490)
at StaticInjector.get (core.js:2353)
at resolveToken (core.js:2564)
at tryResolveToken (core.js:2490)
at StaticInjector.get (core.js:2353)
at resolveNgModuleDep (core.js:26403)
at NgModuleRef_.get (core.js:27491)
at resolveNgModuleDep (core.js:26403)
at resolvePromise (zone-evergreen.js:797)
at resolvePromise (zone-evergreen.js:754)
at zone-evergreen.js:858
at ZoneDelegate.invokeTask (zone-evergreen.js:391)
at Object.onInvokeTask (core.js:34182)
at ZoneDelegate.invokeTask (zone-evergreen.js:390)
at Zone.runTask (zone-evergreen.js:168)
at drainMicroTaskQueue (zone-evergreen.js:559)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:469)
at invokeTask (zone-evergreen.js:1603)
由於上述錯誤建議將ChangeDetectorRef添加為提供程序,因此嘗試在模塊文件中執行此操作。 但是由於ChangeDetectorRef不支持提供程序類型,因此在編譯中再次出現錯誤。
@NgModule({
imports: [
IonicModule,
CommonModule,
FormsModule,
RouterModule.forChild([{ path: '', component: Tab2Page }])
],
declarations: [Tab2Page, SafeurlPipe],
providers: [ChangeDetectorRef]
})
export class Tab2PageModule {}
[ng] ℹ 「wdm」: Compiling...
[ng]
[ng] ERROR in src/app/tab2/tab2.module.ts(17,15): error TS2322: Type 'typeof ChangeDetectorRef' is not assignable to type 'Provider'.
[ng] Type 'typeof ChangeDetectorRef' is not assignable to type 'TypeProvider'.
[ng] Cannot assign an abstract constructor type to a non-abstract constructor type.
[ng]
[ng] Date: 2019-08-12T04:20:20.951Z - Hash: 99468e1aeee0ce99f6f1
[ng] 105 unchanged chunks
** UPDATE(FIX)無法使用組件依賴項注入完成它。 但是,使用組件之間的共享數據服務以及使用rxjs“ Subjects”和subscription能夠實現相同的預期結果。 可以在下面的Angular文檔中找到該過程。 它需要花點時間才能解決,但對於動態UI呈現功能非常強大。
https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
我仍然為為什么無法在離子應用程序中使用ChangeDetectorRef而感到困惑,以防將來可能需要它。
注入ChangeDetectorRef
:
constructor(
private cdr: ChangeDetectorRef,
) {}
然后觸發更改事件:
async updatePics() {
//do something
this.cdr.detectChanges();
}
您不需要使用changeDetectorRef
解決您的問題。 您的問題是在Tab3Page
,您試圖注入Tab2Page
並使用它來調用Tab2Page
函數。 您不能將組件直接注入其他組件中並使用它們。 請參閱文檔,以了解組件之間如何交互。 您可以使用ViewChild調用updatePics()
在Tab3Page
,從構造器中刪除Tab2Page
並添加ViewChild(從@angular/core
導入)
tab3.page.ts
export class Tab3Page implements OnInit {
pics: Picture[] = [];
@ViewChild('tab2') tab2: Tab2Page;
constructor(public fileservice: FileService) {}
ngOnInit() {
console.log('ng init');
this.pics = PICS;
}
saveContent(pic: Picture) {
this.fileservice.savefile(pic);
this.tab2.updatePics();
}
}
在您的html中添加一個模板變量,以便ViewChild
可以訪問該組件。
tab3.page.html
<app-tab2 #tab2 [pics]="pics"></app-tab2>
還有另一種更新數據的方法。 由於pics
是Input
從傳遞Tab3Page
,只需移動updatePics
從Tab2Page
到Tab3Page
並調用它。
tab3.page.ts
export class Tab3Page implements OnInit {
pics: Picture[] = [];
constructor(public fileservice: FileService) {}
ngOnInit() {
console.log('ng init');
this.pics = PICS;
}
saveContent(pic: Picture) {
this.fileservice.savefile(pic);
this.updatePics();
}
async updatePics() {
this.pics = await this.fileservice.getSavedPics();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.