当前位置: 首页 > 知识库问答 >
问题:

如何强制更新Angular中的依赖项注入组件:NullInjectorError:ChangeDetectorRef没有提供程序

微生昌勋
2023-03-14

我有两个UI成分,

Tab3Page:保存数据

Tab2Page:加载数据

Tab2Page被注入到Tab3Page

当数据通过Tabd3Page保存时,我尝试在Tab2Page中自动加载数据。

目前,当我将数据保存在tab3中时,除非手动刷新页面浏览器,否则tab2不会自动更新。有没有办法强制呈现一个类似于react as setState()的页面

以下是组件选项卡3页

@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');
  }

}

数据通过组件选项卡2Page中的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

**更新(修复)无法使用组件依赖注入完成。但是,能够使用组件之间的共享数据服务并使用rxjs“主题”和订阅来实现相同的预期结果。执行过程可以在下面的Angular留档中找到。它需要一点时间来完成,但对于动态UI渲染非常强大。

https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service

我仍然有点担心为什么我不能在ionic应用程序中使用ChangeDetectorRef,以防我将来可能需要它。

共有2个答案

赏高格
2023-03-14

注入ChangeDetectorRef:

  constructor(
    private cdr: ChangeDetectorRef,
  ) {}

然后触发更改事件:

async updatePics() {
    //do something
    this.cdr.detectChanges();
}
袁翰池
2023-03-14

您不需要使用changeDetectorRef来解决您的问题。这里的问题是,在您的选项卡3页面中,您试图注入选项卡2页面,并使用它调用选项卡2页面中的函数。您不能将组件直接注入其他组件并使用它们。查看文档以了解组件如何相互交互。您可以使用ViewChild调用updatePics()

在选项卡3页中,从构造函数中删除选项卡2页,然后添加ViewChild(从角/芯导入)

表3.第页。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中添加模板变量,以便查看子级可以访问组件。

tab3.page.html

<app-tab2 #tab2 [pics]="pics"></app-tab2>

还有一种方法可以更新数据。由于pics是从选项卡3页传递的输入,只需将updatePics从选项卡2页移动到选项卡3页并调用即可。

表3.第页。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();
  }
}
 类似资料:
  • Angular 2的DI系统(大部分)通过来控制。 具体来说是providers 和declarations数组。 (declarations是我们放置组件,管道和指令的地方;providers 是我们提供服务的地方) 例如: 这看起来很简单,但读者会想知道Angular 2如何知道如何构建ChatWidget 。如果ChatWidget是一个字符串或一个简单的函数怎么办? Angular 2假设

  • 问题内容: 我已经阅读了AngularJS文档,但仍然没有我知道的答案。 为什么要使用两次?一次作为数组元素,第二次作为函数参数。 问题答案: 如果缩小此代码: 您将以(类似)结尾: 由于参数名称丢失,因此Angular将无法注入依赖项。 另一方面,如果您将此代码最小化: 您将以: 参数名称可用:Angular的DI可操作。

  • 如何使用新的Angular 2.3组件继承在子组件和父组件之间共享依赖注入? 例如,我想将AlertService移到父组件中,并将TraingCompanyService留在派生组件中 当前组件 重构组件 (V1) 在派生类的构造函数中调用Super之前,必须先调用它 重构组件(V2) 类培训公司编辑组件错误地扩展基类 BaseAdminEditComponent,类型具有单独的私有属性声明“a

  • 我有一个问题加载类到Angular组件。很长一段时间以来,我一直试图解决这个问题;我甚至尝试将它加入到一个文件中。我拥有的是: 一个pplication.ts 服务/名称服务。ts 我一直收到一条错误消息,说。 有人能帮我发现代码的问题吗?

  • 我有以下课程: 这只是其中一个例子,我有一些类似的其他类,我将它们作为依赖注入到其他类中。但是它使我的SchemaFetcher类像一个单例,我不断地向它的每一个方法传递模式定义。这似乎是非常程序化的,我想实际上使模式定义成为数据库模式获取类的实例变量,但在这种情况下,我将无法将模式获取对象注入到我的验证器类中,相反,我应该这样做 但这使我与fetcher紧密耦合,这就是为什么我想首先使用依赖注入