简体   繁体   English

Angular 10 - 修改 model 时视图不更新

[英]Angular 10 - View doesn't update when model is modified

Angular 10.1.6, TypeScript 4.0.5 Angular 10.1.6、TypeScript 4.0.5

Hello你好

Context语境

In my webapp, I have 3 components.在我的 webapp 中,我有 3 个组件。

Component A stores an Array<Image>组件 A存储一个Array<Image>

export class ComponentParentA implements OnInit {
  images: Array <Image> ;

  addImageToList(newImage: Image) {
    this.images.push(newImage)
  }
}

The Component C displays the list of images.组件 C显示图像列表。

export class ComponentChildC implements OnInit {

  @Input() images: Array <Image>;
}

The component C is called from the Component A html template like this:组件 C 从组件 A html 模板调用,如下所示:

<ComponentChildC [images]="images"></ComponentChildC>

Component B is in charge to contact my API, add an image which has been selected previously. B组负责联系我的API,加一张之前选好的图。 The API return an Image object, which correspond to my model. API返回一个Image object,对应我的model。 The component emit the Image so the ComponentA add the returned image to its Array (Calling addImageToList)组件发出图像,因此 ComponentA 将返回的图像添加到其数组中(调用 addImageToList)
addImage is an Observable return by this.http.post ( HttpClient ) addImage 是 this.http.post ( HttpClient ) 的 Observable 返回

export class ComponentChildB implements OnInit, AfterViewInit {
  @Output() eventCreateImage : EventEmitter<Image>;

  addImage(data) {
    this.service.addImage(data).subscribe((image) => {
        this.eventCreateImage.emit(image)
      })
  }

}

Component A calls Component B like this:组件 A 像这样调用组件 B:

<ComponentChildB (eventCreateImage)="addImageToList($event)"></ComponentChildB>

Problem问题

The Component B add an image when I click on a button.当我单击按钮时,组件 B 添加图像。 This click trigger the addImage function.此点击触发addImage function。 All the component work correctly and the image is save on my server.所有组件都正常工作,图像保存在我的服务器上。 The API returns the image and the latter is correctly stored in the Array in Component A. However, the view of the component C is not updated and the newly created image doesn't appear. API 返回图像,后者正确存储在组件 A 的数组中。但是,组件 C 的视图没有更新,新创建的图像也没有出现。 If I click a second time on the button, a new image is stored.如果我再次单击该按钮,则会存储一个新图像。 This time, the previous image, which I couldn't see previously, appears correctly.这一次,我之前看不到的之前的图像正确显示了。 The new image don't.新图没有。

I would like the image to appear directly.我希望图像直接出现。

What I already did我已经做过的

I saw similar issues on the web.我在 web 上看到了类似的问题。

  • First , I tried to replace this.images.push(newImage) by this.images = this.images.concat(newImage) in addImageToList function. 首先,我尝试在addImageToList function 中用this.images = this.images.concat(newImage)替换this.images.push(newImage) It doesn't work.它不起作用。
  • Next, I saw that, because images is an array, Angular doesn't detect any change when I add a new Image in my array.接下来,我看到了,因为 images 是一个数组,所以当我在数组中添加新图像时,Angular 没有检测到任何变化。 I made my Component C implements the OnChange interface.我让我的组件 C 实现了 OnChange 接口。 Effectively, the ngOnChange function is not called.实际上,不会调用 ngOnChange function。
  • I saw here that I could try to reload my component manually So I made my Component C implement DoCheck.我在这里看到我可以尝试手动重新加载我的组件所以我让我的组件 C 实现 DoCheck。 Something strange appeared.奇怪的东西出现了。 When I click on the button and I do console.log(this.images) in ngDoCheck in component C, I see that the list is correctly updated.当我单击按钮并在组件 C 的 ngDoCheck 中执行console.log(this.images)时,我看到列表已正确更新。 But the image still doesn't appear.但是图像仍然没有出现。 So I try to call ChangeDetectorRef methods like markForCheck and detectChanges to notify the component of the change, but it didn't work.所以我尝试调用诸如 markForCheck 和 detectChanges 之类的ChangeDetectorRef方法来通知组件发生了变化,但是没有成功。

If you have any idea where my problem may be coming from, I would be grateful if you could help me如果您知道我的问题可能来自哪里,如果您能帮助我,我将不胜感激

I didn't test but i think it's cause strategy detection.我没有测试,但我认为这是导致策略检测的原因。 You can try 3 differents solutions (I can't test now but normaly it will be work).您可以尝试 3 种不同的解决方案(我现在无法测试,但通常它会起作用)。

PS: sorry for my english PS:对不起我的英语

1/ in your object @Component add changeDetection in your components 1/ 在您的 object @Component 在您的组件中添加 changeDetection

@Component({
  selector: 'app-component',
  template: `...`,
  changeDetection: ChangeDetectionStrategy.OnPush
})

then in your function addImageToList() replace your code by然后在你的 function addImageToList() 替换你的代码

addImageToList(newImage) {
   this.images = [...this.images, newImage]
}

2/ in your component C replace your @Input by 2/ 在您的组件 C 中,将您的 @Input 替换为

@Input() set images(value: Array <Image>) {
      myImages = value
 }

the properties binding in html will be myImages in this context html 中的属性绑定将是 myImages 在此上下文中

3/ You can change manualy the strategy detection with the service ChangeDetectorRef. 3/ 您可以使用服务 ChangeDetectorRef 手动更改策略检测。 Add this service in your constructor component A then in your function add:在您的构造函数组件 A 中添加此服务,然后在 function 中添加:

constructor(
     private cd: ChangeDetectorRef
   ){}

  addImageToList(newImage: Image) {
    this.images = [...this.images, newImages];
    this.cd.markForCheck();
  }

If this solutions don't work look the documentation of detection strategy in Angular or try to mix 1 and 2 together如果此解决方案不起作用,请查看 Angular 中的检测策略文档或尝试将 1 和 2 混合在一起

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM