【问题标题】:How can I patch an image field in a reactive form in Angular?如何在 Angular 中以反应形式修补图像字段?
【发布时间】:2021-06-29 10:31:36
【问题描述】:

我正在努力解决这个问题。我有一个创建项目的表单,这个项目可以有一个缩略图。为了上传图片,我使用了ngx-mat-file-input 库。我创建上传如下:

component.html:

                        <mat-form-field>
                            <ngx-mat-file-input #photo  formControlName="photo" placeholder="Image" (change)="onAddImage($event)"></ngx-mat-file-input>
                            <button mat-icon-button matSuffix *ngIf="!photo.empty" (click)="photo.clear($event); ">
                                <mat-icon matSuffix>clear</mat-icon>
                            </button>
                            <mat-icon matSuffix  *ngIf="photo.empty">photography</mat-icon>

                            <mat-error *ngIf="hasError('photo', 'maxContentSize')">
                                The total size must not exceed {{itemForm.get('photo')?.getError('maxContentSize').maxSize | byteFormat}} ({{itemForm.get('photo')?.getError('maxContentSize').actualSize
                            | byteFormat}}).
                            </mat-error>
                        </mat-form-field>
                        <div *ngIf="!photo.empty" style="float: left; margin: 5px">
                            <img [src]="imageSrc" *ngIf="imageSrc" style="max-height: 100px; max-width:100x">
                        </div>

然后我的打字稿中有这些方法: component.ts:

  // properties
  readonly photoMaxSize = 2*2**20; // 2MB
  imageSrc: string | undefined; // Used to preview image
  itemForm: FormGroup;

  // constructor
  this.itemForm = new FormGroup({
        photo:              new FormControl(undefined, [FileValidator.maxContentSize(this.photoMaxSize)]),
        name:               new FormControl('', [Validators.required, Validators.maxLength(100)]),  
   });

  // validation
  hasError(controlName: string, errorName: string){
    return this.itemForm.controls[controlName].hasError(errorName);
  }

  // create thumbnail when creating the form
   onAddImage(event: any) {
    const reader = new FileReader();
    if(event.target.files && event.target.files.length) {
      const [file] = event.target.files;
      reader.readAsDataURL(file);
      reader.onload = () => {
        this.imageSrc = reader.result as string;
        this.itemForm.patchValue({
          fileSource: reader.result
        });
      };
    }
  }

我的问题来了,它被发送到后端,然后作为包含图像 URL 的 JSON 返回,所以我开始在我的表单中创建类似这样的东西来修补值:

patchFormOnEdit(id: number){
    this.itemService.getItem(id).subscribe(
      (res: Item) =>{
        
        // Patch strings
        this.itemForm.patchValue({
          name: res.name,
        });
        
        // Thumbnail:
        if (res.photo){
          console.log("Setting thumbnail to " + res.photo);
          this.imageSrc = res.photo;
          this.itemForm.patchValue({
            photo: res.photo,
          });
        }
      }
    );
  }

但它已经崩溃了:

R TypeError: control.value.files is undefined
    maxContentSize ngx-material-file-input.js:403
    Angular 9
    patchFormOnEdit XXXX.component.ts:140
    RxJS 13
    Angular 16
    RxJS 18
    patchFormOnEdit XXXX.component.ts:107
    ngOnInit .component.ts:101
    Angular 22
    RxJS 5
    Angular 22
    ItemTableComponent_td_39_Template YYYY.component.html:129
    Angular 11
    RxJS 5

我的猜测是我无法将 URL 映射到库使用的对象类型。我该如何解决这个问题?

我的目标是与我创建的相同,我可以在其中删除或更改项目,但使用已保存在后端的内容作为 src,而不是用户在创建时输入的内容:

【问题讨论】:

    标签: angular forms file-upload angular-reactive-forms patch


    【解决方案1】:

    我找到了一个我不知道它是否正确的解决方案,但至少有点工作。

    我无法使用ngx-mat-file-input 来显示我从后端获得的图像,我不知道这是否可行,或者它是否只是处理来自用户的本地文件。

    所以我创建了一个选择框来删除该项目:

    component.ts:

      previousImageSrc: string | undefined; // Used to store previous image
      deletePreviousImage: boolean | undefined = undefined; // Delete backend image on patch
       ...
       ...
            // Patch Thumbnail:
            if (res.photo){
              this.imageSrc=res.photo;
              this.previousImageSrc=res.photo;
              this.deletePreviousImage = false;
            }
    ...
    ...
    // Add image using the nxg-mat-file-input
    onAddImage(event: any) {
        const reader = new FileReader();
        if(event.target.files && event.target.files.length) {
          const [file] = event.target.files;
          reader.readAsDataURL(file);
          reader.onload = () => {
            this.imageSrc = reader.result as string;
            this.itemForm.patchValue({
              fileSource: reader.result
            });
          };
          this.deletePreviousImage = false;
        }
      }
    
      // When the user removes an image display again what is in backend
      onRemoveImage(){
        if(this.previousImageSrc){
          this.imageSrc = this.previousImageSrc;
          this.deletePreviousImage = false;
        }
      }
    
    

    然后更新 html 以包含这个删除图像功能:

    component.html

                 <!-- Photo -->
                        <div class="row-group">
    
                            <mat-form-field>
                                <ngx-mat-file-input #photo  formControlName="photo" placeholder="Image" (change)="onAddImage($event)"></ngx-mat-file-input>
                                <button mat-icon-button matSuffix *ngIf="!photo.empty" (click)="photo.clear($event); onRemoveImage()">
                                    <mat-icon matSuffix>clear</mat-icon>
                                </button>
                                <mat-icon matSuffix  *ngIf="photo.empty">photography</mat-icon>
    
                                
    
                                <mat-error *ngIf="hasError('photo', 'maxContentSize')">
                                    The total size must not exceed {{itemForm.get('photo')?.getError('maxContentSize').maxSize | byteFormat}} ({{itemForm.get('photo')?.getError('maxContentSize').actualSize
                                | byteFormat}}).
                                </mat-error>
                            </mat-form-field>
                            
                            <div *ngIf="imageSrc" style="float: left; margin: 5px">
    
                                <!-- Display Preview -->
                                <img [src]="imageSrc" alt='Item image' *ngIf="imageSrc" style="max-height: 100px; max-width:100x">
                               
                                <!-- deletePreviousImage -->
                                <div  *ngIf="deletePreviousImage !== undefined && photo.empty">
                                    <br>
                                    <mat-checkbox
                                        class="checkbox"
                                        formControlName="deletePreviousImage"
                                        id="item:edit:deletePreviousImage"
                                        >
                                        Delete image
                                    </mat-checkbox>
                                </div>
                            </div>
                        </div>
    

    按照问题的例子,这看起来像这样:

    【讨论】:

      猜你喜欢
      • 2020-11-07
      • 1970-01-01
      • 2019-11-03
      • 2018-04-16
      • 1970-01-01
      • 2018-03-23
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多