1

I'm trying to render a dynamic FormArray (When "+" is clicked it should add a new), but always when I put some file in the input box the Message ("Nenhum Arquivo Selecionado" which means "File Doesn't Exist") stays on the screen.

enter image description here

However, if I check the info on this.filterForm.get('Documents'), the row is filled correctly.

Does anyone have a sugestion to fix this error?

protocolo.component.ts

items: FormArray;

  filterForm = new FormGroup({
    IdProtocolo: new FormControl(),
    Documentos: this.formBuilder.array([ this.createItem() ]
  );

  ngOnInit() {
    this.items = this.filterForm.get('Documentos') as FormArray;
  }

  createItem(): FormGroup{
    return this.formBuilder.group({
      filename: '',
      filetype: '',
      value: ''
    })
  }

  addItem(){
    this.items.push(this.createItem());
  }

  removeItem(index){
    if(this.items.length > 1) {
      this.items.removeAt(index);
    }
  }

  onFileChange(event: any, index: any) {
    let reader = new FileReader();

    if(event.target.files && event.target.files.length > 0) {
      let file = event.target.files[0];
      reader.readAsDataURL(file);
      this.items.at(index).patchValue({
        filename: file.name,
        filetype: file.type,
        value: (reader.result as string).split(',')[1]
      })
    }
  }

protocolo.component.html

<div *ngFor="let item of filterForm.value.Documentos; let i = index;">
  <div class="row" style="margin-bottom: 10px;">
      <div class="col-md-4">
        <input type="file" formControlName="Documentos" (change)="onFileChange($event, i)">
      </div>
      <div class="col-md-8">
        <button class="btn btn-success-tce" (click)="addItem()">+</button>
        <button class="btn btn-success-tce" (click)="removeItem(i)"style="margin-left: 5px">-</button>
      </div>
  </div>

1 Answer 1

1

[Updated] Possibly wrong implementation of formArray. I cannot see a formArrayName in your template. I would have implemented this like

In your template

<p> Dynamic File Form </p>
<form [formGroup]="someForm" (submit)="formSubmit()">
  <div formArrayName="documents">
    <div *ngFor="let item of files?.controls; let i = index;"> 
      <input type="file" placeholder="Upload file" [formControlName]="i" (change)="onFileChange($event, i)"/>
    </div>
  </div>
  <button type="submit"> Submit </button>
</form>

<button type="button" (click)="addFileControl()"> Add File </button>

In your component.

  initForm() {
    this.someForm = this.fb.group({
      documents: this.fb.array([this.fileControl])
    })
  }

  get files() {
    return this.someForm.get('documents') as FormArray;
  }

  get fileControl() {
    return this.fb.group({
      file_item: [null]
    })
  }

  addFileControl() {
    this.files.push(this.fileControl);
  }

  formSubmit() {
    console.log(this.someForm.value);
  }

  onFileChange(event, i) {
    let reader = new FileReader();

    if (event.target.files && event.target.files.length) {
      const [file] = event.target.files;
      reader.readAsDataURL(file);

      reader.onload = () => {
        this.files.controls[i].get('file_item').setValue(reader.result);

        // need to run CD since file load runs outside of zone
        this.cd.markForCheck();
      };
    }
  } 

Here is the stackblitz example. This will give you the output in base64 format but you can also get it in file format by modifying.

onFileChange(event, i) {
  if (event.target.files && event.target.files.length) {
    this.files.controls[i].get('file_item').setValue(event.target.files;);
   }
}

Note:- It is just a rough code but does the job :).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.