簡體   English   中英

如何在Angular中強制更新依賴項注入組件:NullInjectorError:沒有ChangeDetectorRef的提供程序

[英]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>

還有另一種更新數據的方法。 由於picsInput從傳遞Tab3Page ,只需移動updatePicsTab2PageTab3Page並調用它。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM