代码之家  ›  专栏  ›  技术社区  ›  Ron

ngmodel的更新值未反映在组件内部

  •  0
  • Ron  · 技术社区  · 7 年前

    我有一个组件 ControlValueAccessor 实现,但当绑定值在组件外部更改时,它不会正确更新。

    编辑:
    stackblitz示例: https://stackblitz.com/edit/angular-lmojnj

    我来解释塞纳里奥。
    一开始数组中有两个图像,如果我单击其中一个图像,它将触发 toggleSelected 将临时图像更新为只有一个图像(未单击的图像)的图像排序器。
    然后,如果我在parent.component的输入中输入图像的url并单击enter,它将触发 addImage 将URL推送到的parent.component的 tempImages 因此,应该在图像分类程序中执行逻辑(调用writevalue会自动导致值更改吗?-但事实并非如此)。 现在,如果我单击之前单击的同一个图像(或选择的另一个图像),则显示之前添加的新图像! 当我把它添加到 风暴意象 数组,因为它是双向绑定,不是吗?

    为了解决这个问题,我添加了对图像分类程序的引用( <app-images-sorter2 #imagesSorter [(ngModel)]="tempImages"></app-images-sorter2> ) 然后将引用传递给addimage并调用 imageSorterCompoennt.writeValue(this.tempImages); 它更新了我的期望,但据我所知,这是一种不好的做法和错误的解决方案

    images-sorter2.组件.ts:

    import { Component, forwardRef, ViewEncapsulation } from '@angular/core';
    import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
    
    @Component({
      selector: 'app-images-sorter2',
      templateUrl: './images-sorter2.component.html',
      styleUrls: ['./images-sorter2.component.scss'],
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => ImagesSorter2Component),
          multi: true
        }
      ],
      encapsulation: ViewEncapsulation.None
    })
    export class ImagesSorter2Component implements ControlValueAccessor {
      public allImages: string[] = [];
      public images: string[] = [];
    
      private onChange: (_: any) => void = () => {};
    
      constructor() {}
    
      public writeValue(value: string[]): void {
        this.images = value || [];
        this.images.forEach((image) => {
          if (!this.allImages.includes(image)) {
            this.allImages.push(image);
          }
        });
        this.onChange(this.images);
      }
    
      public registerOnChange(fn: (_: any) => void): void {
        this.onChange = fn;
      }
    
      public registerOnTouched(): void {}
    
      public isSelected(image: string): boolean {
        return this.images.includes(image);
      }
    
      public getImageModelIndex(image: string): number {
        return this.images.indexOf(image);
      }
    
      public toggleSelected(image: string): void {
        const indexOfImage = this.getImageModelIndex(image);
        let newValue;
        if (indexOfImage > -1) {
          newValue = [...this.images.slice(0, indexOfImage), ...this.images.slice(indexOfImage + 1)];
        } else {
          newValue = [...this.images, image];
        }
        this.writeValue(newValue);
      }
    }
    

    images-sorter2.component.html文件:

    <div fxLayout="row wrap">
      <div *ngFor="let image of allImages"
           class="image-wrapper"
           [ngClass]="{'selected': isSelected(image)}"
           (click)="toggleSelected(image)">
        <div class="index-container">
          <div>{{ getImageModelIndex(image)+1 }}</div>
        </div>
        <div class="image-container">
          <img [src]="image" />
        </div>
      </div>
    </div>
    

    父.component.ts:

    import { Component, ViewEncapsulation } from '@angular/core';
    
    @Component({
      selector: 'app-parent',
      templateUrl: './parent.component.html',
      styleUrls: ['./parent.component.scss'],
      encapsulation: ViewEncapsulation.None
    })
    export class ParentComponent {
      public tempImages = [
        'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Google_Chrome_icon_%28September_2014%29.svg/1200px-Google_Chrome_icon_%28September_2014%29.svg.png',
        'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/1200px-Apple_logo_black.svg.png'
      ];
      public newImage: string = '';
    
      public addImage(): void {
        this.tempImages.push(this.newImage);
        this.newImage = '';
      }
    }
    

    parent.component.html(父组件):

    <app-images-sorter2 [(ngModel)]="tempImages"></app-images-sorter2>
      <div>
        <mat-form-field>
          <input matInput
                 type="text"
                 [(ngModel)]="newImage"
                 (keyup.enter)="addImage()"
                 placeholder="Image URL">
        </mat-form-field>
      </div>
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   NiQu    7 年前

    我以前遇到过这个问题,而且看来ControlValueAccesor在注意集合更改方面有问题,所以您必须重新分配数组。

    例如,将parent.ts文件中的第18行从

    this.tempImages.push(this.newImage);
    

    this.tempImages = this.tempImages.concat([this.newImage]);
    

    它应该可以正常工作。

        2
  •  0
  •   androbin    7 年前

    没有功能 includes string[] 正如斯特克布利茨所显示的那样。

    根据 docs 它应该可以工作,但是在将其替换为 .indexOf(image) === -1 它起作用了。 Example

    推荐文章