簡體   English   中英

如何在 Angular 中以反應形式修補圖像字段?

[英]How can I patch an image field in a reactive form in Angular?

我正在努力解決這個問題。 我有一個創建項目的表單,這個項目可以有一個縮略圖。 為了上傳圖片,我使用了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>

然后我在我的 typescript: 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
        });
      };
    }
  }

我的問題來了,它被發送到后端,然后作為 JSON 返回,其中包含一個 URL 到圖像,所以我開始在我的表單中創建類似這樣的東西來修補值:

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

我的猜測是我不能 map 將 URL 轉換為圖書館使用的 object。 我該如何解決這個問題?

我的目標是與我創建的相同,我可以在其中刪除或更改項目,但使用已保存在后端的內容作為 src,而不是用戶在創建時輸入的內容: image_filed

我找到了一個解決方案,我不知道它是否是正確的方法,但至少是可行的。

我無法使用ngx-mat-file-input來顯示我從后端獲得的圖像,我不知道它是否可能,或者它是否只處理來自用戶的本地文件。

所以我創建了一個 select 框來刪除該項目:

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 以包含此刪除映像 function:

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>

按照問題的例子,這看起來像這樣: 示例選擇框

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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