如何使用formBuilder在angular2中为新的嵌套JSON数据插入新图像?

时间:2016-10-27 09:36:25

标签: arrays json forms angular formbuilder

我想要做的是使用formBuilder创建带有图像的JSON数据以保存到firebase数据库中,但首先我需要在主JSON数据中创建嵌套数组数据,其中包含每个数组的图像,我需要每个插入新图像的数组数据

我的JSON数据中包含嵌套的formArray:

{
  "nomor_transaksi": "",
  "returDetails": [
    {
      "kd_brg": "",
      "qty": "",
      "pengaduan": "",
      "kd_lokasi": "",
      "picture": ""
    },
    {
      "kd_brg": "",
      "qty": "",
      "pengaduan": "",
      "kd_lokasi": "",
      "picture": ""
    }
  ]
}

这是我的HTML代码:

<form [formGroup]="datareturForm" (ngSubmit)="submitForm()">

      <div class="form-group">
        <label for="nomor_transaksi">Nomor Transaksi</label>
        <input #notrans type="text" placeholder="nomor transaksi" formControlName="nomor_transaksi"/>
        <p *ngIf="datareturForm.controls.nomor_transaksi.errors">Pelan2 bro, max 10 char ya</p>
      </div><br/>

      <!-- details mulai disini-->

      <div class="form-group">
        <div formArrayName="returDetails">
          <p>List Barang : </p>
          <div *ngFor="let retur of returDetails.controls; let i=index" [formGroupName]="i">
            <label for="kd_brg">Kode Barang</label>
            <input type="text" placeholder="Kode Barang" formControlName="kd_brg"/>
            <!--<p *ngIf="returDetails.controls.kd_brg.errors">Pelan2 bro, max 10 char ya</p>-->

            <label for="qty">Qty</label>
            <input type="text" placeholder="Qty" formControlName="qty"/>
            <!--<p *ngIf="returDetails.controls.kd_brg.errors">Pelan2 bro, max 10 char ya</p>-->

            <label for="pengaduan">Pengaduan</label>
            <input type="text" placeholder="Pengaduan" formControlName="pengaduan"/>
            <!--<p *ngIf="returDetails.controls.kd_brg.errors">Pelan2 bro, max 10 char ya</p>-->

            <label for="kd_lokasi">Kode Lokasi</label>
            <input type="text" placeholder="Kode Barang" formControlName="kd_lokasi"/>
            <!--<p *ngIf="returDetails.controls.kd_brg.errors">Pelan2 bro, max 10 char ya</p>-->

            <label for="gambar">Gambar</label>
            <input type="file" (change)="onChange($event)" />

            <label for="preview">Preview</label>
            <img [src]="fileupload">
          </div>
        </div>
      </div><br/>

      <button type="submit">Save Contact</button>
      <button type="button" (click)="deleteRetur(notrans.value)">Delete</button>
      <br/>

    </form>
<button (click)="add()">Add Detail</button>

每次我点击“添加详细信息”按钮,它将为新行数据创建新的数组JSON,我在表单外面添加“添加详细信息”按钮,因为如果我把它放在表单中,那表单会认为我点击并提交。

这是我的打字稿代码:

  datareturForm: FormGroup;
  returDetails: FormArray;
  items: FirebaseListObservable<any[]>;
  fileupload: any;

  ngOnInit(){

    this.datareturForm = this.formBuilder.group({
      nomor_transaksi: ['', Validators.maxLength(20)],
      returDetails: this.bikinArray()
    })

  }

  bikinArray(): FormArray {
    this.returDetails = this.formBuilder.array([
      this.buildGroup()
    ]);
    return this.returDetails;
  }

  buildGroup(): FormGroup {
    return this.formBuilder.group({
      kd_brg:'',
      qty:'',
      pengaduan:'',
      kd_lokasi:'',
      gambar:''
    });
  }

  add() {
    this.returDetails.push(this.buildGroup());
  }

    onChange(input): void {



          // Create an img element and add the image file data to it
          var img = document.createElement("img");
          // var img:any = new Image();
          img.src = window.URL.createObjectURL(input.target.files[0]);

          // Create a FileReader
          var reader: any, target: EventTarget;
          reader = new FileReader();
          // var that = this;
          // Add an event listener to deal with the file when the reader is complete
          reader.addEventListener("load", (event) => {
              // Get the event.target.result from the reader (base64 of the image)
              img.src = event.target.result;

              // Resize the image
              var resized_img = this.resize(img,input.target.files[0].type);
              // that.cropper.setImage(img);
              // Push the img src (base64 string) into our array that we display in our html template
              this.fileupload=resized_img;


              // this.file=dataUrl;
              // var imgBlob = this.dataURItoBlob(this.file);
              // this.fileupload = imgBlob

          }, false);

          reader.readAsDataURL(input.target.files[0]);
        }

        resize (img, type, MAX_WIDTH:number = 700, MAX_HEIGHT:number = 700){

          var canvas = document.createElement("canvas");

          // console.log("Size Before: " + img.src.length + " bytes");

          var width = img.width;
          var height = img.height;

          if (width > height) {
              if (width > MAX_WIDTH) {
                  height *= MAX_WIDTH / width;
                  width = MAX_WIDTH;
              }
          } else {
              if (height > MAX_HEIGHT) {
                  width *= MAX_HEIGHT / height;
                  height = MAX_HEIGHT;
              }
          }
          canvas.width = width;
          canvas.height = height;
          var ctx = canvas.getContext("2d");

          ctx.drawImage(img, 0, 0, width, height);

          var dataUrl = canvas.toDataURL(type);  
          // IMPORTANT: 'jpeg' NOT 'jpg'
          // console.log("Size After:  " + dataUrl.length  + " bytes");
          return dataUrl
        }

每次我点击添加细节按钮它将创建新的嵌套数组但图像保持循环相同的图像,我想添加新图像: Screenshot

看到它循环相同的图像,当我替换其中一个阵列图像时,其他人也不断更改相同的图像。我需要每一行都是不同的图像,我该怎么做?

=============================================

更新

我刚刚更新了我的代码,就像@Fabio Antunes回答一样,我得到的是这个错误:

  

error_handler.js:45 EXCEPTION:无法设置属性'picture'   undefinedErrorHandler.handleError @ error_handler.js:45next @   application_ref.js:273schedulerFn @   async.js:82SafeSubscriber .__ tryOrUnsub @   Subscriber.js:223SafeSubscriber.next @   Subscriber.js:172Subscriber._next @ Subscriber.js:125Subscriber.next @   Subscriber.js:89Subject.next @ Subject.js:55EventEmitter.emit @   async.js:74onError @ ng_zone.js:120onHandleError @   ng_zone_impl.js:64ZoneDelegate.handleError @ zone.js:207Zone.runTask @   zone.js:139ZoneTask.invoke @ zone.js:304 error_handler.js:50 ORIGINAL   STACKTRACE:ErrorHandler.handleError @ error_handler.js:50next @   application_ref.js:273schedulerFn @   async.js:82SafeSubscriber .__ tryOrUnsub @   Subscriber.js:223SafeSubscriber.next @   Subscriber.js:172Subscriber._next @ Subscriber.js:125Subscriber.next @   Subscriber.js:89Subject.next @ Subject.js:55EventEmitter.emit @   async.js:74onError @ ng_zone.js:120onHandleError @   ng_zone_impl.js:64ZoneDelegate.handleError @ zone.js:207Zone.runTask @   zone.js:139ZoneTask.invoke @ zone.js:304 error_handler.js:51   TypeError:无法设置未定义的属性“picture”       在FileReader。 (app.component.ts:115)       在ZoneDelegate.invokeTask(zone.js:236)       at Object.onInvokeTask(ng_zone_impl.js:34)       在ZoneDelegate.invokeTask(zone.js:235)       在Zone.runTask(zone.js:136)       在FileReader.ZoneTask.invoke(zone.js:304)ErrorHandler.handleError @ error_handler.js:51next @   application_ref.js:273schedulerFn @   async.js:82SafeSubscriber .__ tryOrUnsub @   Subscriber.js:223SafeSubscriber.next @   Subscriber.js:172Subscriber._next @ Subscriber.js:125Subscriber.next @   Subscriber.js:89Subject.next @ Subject.js:55EventEmitter.emit @   async.js:74onError @ ng_zone.js:120onHandleError @   ng_zone_impl.js:64ZoneDelegate.handleError @ zone.js:207Zone.runTask @   zone.js:139ZoneTask.invoke @ zone.js:304 app.component.ts:115 Uncaught   TypeError:无法设置undefined(...)

的属性“picture”

以下是外观: Preview

我认为它不会绑定到我的json树吗?怎么绑呢? 我确实添加了我的HTML代码:

    <label for="gambar">Gambar</label>
    <input type="file" (change)="onChange($event,i)" formControlName="picture"/>

    <label for="preview">Preview</label>
    <img [src]="retur.picture">

但没有发生任何事情,仍然我得到了相同的错误,我试图谷歌关于formBuilder /反应形式处理它没有显示结果,在这里需要帮助,不知道搜索什么

1 个答案:

答案 0 :(得分:0)

因为我认为在formBuilder中没有任何绑定函数,因为我在app.component.ts中注入了JSON手册,所以我做了以下操作:

在我的app.component.html中添加

    <label for="gambar">Gambar</label>
    <input type="file" (change)="onChange($event,i)" />

    <label for="preview">Preview</label>
    <img [src]="retur.value.picture">

注意我不能用dunno访问json值为什么,我在我朋友的帮助下尝试和错误很多

然后下面是我的app.component.ts:

  ngOnInit(){

    this.datareturForm = this.formBuilder.group({
      nomor_transaksi: ['', Validators.maxLength(20)],
      returDetails: this.bikinArray()
    })

  }

  bikinArray(): FormArray {
    this.returDetails = this.formBuilder.array([
      this.buildGroup()
    ]);
    return this.returDetails;
  }

  buildGroup(): FormGroup {
    return this.formBuilder.group({
      kd_brg:'',
      qty:'',
      pengaduan:'',
      kd_lokasi:'',
      namafile:'',
      picture: '',
      hasilImgBlob: ''
    });
  }

      add() {
        this.returDetails.push(this.buildGroup());
      }

onChange(input, index): void {

      // Create an img element and add the image file data to it
      var img = document.createElement("img");
      // var img:any = new Image();
      img.src = window.URL.createObjectURL(input.target.files[0]);

      //ambil nama file
      this.returDetails.controls[index].value.namafile=input.target.files[0].name;
      // console.log(this.namafile);

      // Create a FileReader
      var reader: any, target: EventTarget;
      reader = new FileReader();
      // var that = this;
      // Add an event listener to deal with the file when the reader is complete
      reader.addEventListener("load", (event) => {
          // Get the event.target.result from the reader (base64 of the image)
          img.src = event.target.result;

          // Resize the image
          var resized_img = this.resize(img,input.target.files[0].type);
          // that.cropper.setImage(img);
          // Push the img src (base64 string) into our array that we display in our html template
          this.fileupload=resized_img;

          this.returDetails.controls[index].value.picture=resized_img;

          var imgBlob = this.dataURItoBlob(this.fileupload);
          this.returDetails.controls[index].value.hasilImgBlob=imgBlob

          //ini kasi nama baru aja, terus nanti yg ini yg di save
          // this.hasilImgBlob[] = imgBlob
          //indexing gambar
          // this.returDetails[index].picture = resized_img;
          // console.info(index);

          // this.file=dataUrl;

      }, false);

      reader.readAsDataURL(input.target.files[0]);
    }

    //you need this function to convert the dataURI
    dataURItoBlob(dataURI) {
      var binary = atob(dataURI.split(',')[1]);
      var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
      var array = [];
      for (var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
      }
      return new Blob([new Uint8Array(array)], {
        type: mimeString
      });
    }

    resize (img, type, MAX_WIDTH:number = 700, MAX_HEIGHT:number = 700){

      var canvas = document.createElement("canvas");

      // console.log("Size Before: " + img.src.length + " bytes");

      var width = img.width;
      var height = img.height;

      if (width > height) {
          if (width > MAX_WIDTH) {
              height *= MAX_WIDTH / width;
              width = MAX_WIDTH;
          }
      } else {
          if (height > MAX_HEIGHT) {
              width *= MAX_HEIGHT / height;
              height = MAX_HEIGHT;
          }
      }
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext("2d");

      ctx.drawImage(img, 0, 0, width, height);

      var dataUrl = canvas.toDataURL(type);  
      // IMPORTANT: 'jpeg' NOT 'jpg'
      // console.log("Size After:  " + dataUrl.length  + " bytes");
      return dataUrl
    }


    save():void{
        if(this.fileupload==undefined){
            //ini bagian, save tanpa image ke storage
              //this.items.push(this.profileData);
        }else{
              event.preventDefault();
              //loop si retur.control
              for(var i = 0; i < this.returDetails.length ; i++){

                // ini dapetin nama file image
                let namaFileEdited:string= new Date().getTime()+'-'+this.returDetails.controls[i].value.namafile;

                let storageRef: any = firebase.storage().ref();
                //ini lokasi storage u folder n nama nya apa
                let path: string = 'images/' + namaFileEdited;
                //ini fungsi, save ke storage, (image nya)

                 let uploadTask: any = storageRef.child(path).put(this.returDetails.controls[i].value.hasilImgBlob);

                  //ini progress nya
                  uploadTask.on('state_changed', (snapshot)=> {
                    var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
                      console.log('Upload is ' + progress + '% done');
                      switch (snapshot.state) {
                        case firebase.storage.TaskState.PAUSED: // or 'paused'
                          console.log('Upload is paused');
                          break;
                        case firebase.storage.TaskState.RUNNING: // or 'running'
                          console.log('Upload is running');
                          break;
                      }
                  }, (error) => {
                    //ini klo error
                    console.info('dafuq error bro');
                  }, () =>{
                    //ini completed
                    //ini ambil nama file, masukin ke json profiledata
                    this.datareturForm['namafile']=namaFileEdited;
                    //ini ambil link gambar di storage, masukin ke json profile data
                    this.datareturForm['picture']=uploadTask.snapshot.downloadURL;

                     //save ke database
                    this.items.push(this.datareturForm.value)
                  });
              }

        }

    }

对不起印尼语言的许多评论,不要介意,这是我自己的笔记。你们可以在那里看到我在onChange函数中添加了returDetails.picture,看看这一行this.returDetails.controls[index].value.picture=resized_img;

我将resized_img添加到json变量中,所以这里的json会是这样的:

enter image description here

正如你所看到的那样,我选择的图像没有被添加到json变量中,但现在我添加了它,如果你在脑海中有关于“hasilImgBlob”的问题,那么它是我添加到JSON变量中的图像数据BLOB,但结果只是{}仍然我不知道为什么,但当我把它推入firebase时,它保存了hola!我无法看到{}我只能调试对象,希望这个小代码可以帮助对方。并且不介意我跳过的JSON变量,它不是我不想写它,但它是与第一个“nomor_transaksi”相同的变量。我跳过它,因为它太多了

注意:此代码用于推送到firebase数据库,图像保存到firebase存储中。由于BLOB数据保存在json数据库文件中,因此该代码仍未满足我的要求,但本主题与此无关。因为我已经将它保存到firebase存储中,所以最好保存firebase存储的URL