shutupandshave
shutupandshave

Reputation: 39

Angular - validating data driven forms with custom components

I've a form with a custom file upload component. Dependent on server data I may need multiple components on the same page.

I'm struggling to get the validation working. I.E. the "isInvalid" function within the custom form component.

get isInvalid(): boolean {
  const formEl = this.form.get('inputFile');
  if (!formEl) {
    return true;
  }

  return formEl.touched && formEl.invalid;
}

This cant be some kind of unsolved problem but I've asked a few people in my network and we couldn't figure out how to get it working. Can anyone suggest either a better approach to making this work or some changes to my code please?

I've included a stackblitz to demonstrate the problem: which is that my custom component validation seems to have no idea who/where it is in relation to the form. What's interesting is that I can delete/add files to the form itself without problem.

StackBlitz

Upvotes: 0

Views: 197

Answers (1)

Titus Sutio Fanpula
Titus Sutio Fanpula

Reputation: 3613

There's something wrong in your upload component. You can look at code below:

Use @Input() formControlName in your custom component

@Input() formControlName: string

After that, you can look at your custom component constructor:

Your constructor

constructor(private rootFormGroup: FormGroupDirective) {}

You can change that constructor with code below:

constructor(private controlContainer: ControlContainer) {}

After that, in your ngOnInit you can change initialization form like this:

this.form = this.controlContainer.control as FormGroup;

And in your isValid and isInvalid you can change const formEl with code below:

const formEl = this.form.get(this.formControlName);

For final code in your html you can try with code below:

<!-- No File uploaded yet -->
<ng-container [formGroup]="form">
  <div class="" *ngIf="!file" (click)="fileUpload.click()">
    <label [for]="id" class="" (click)="$event.preventDefault()">
      <strong>{{ inputLabel }}</strong>
    </label>
    <!-- Plus Icon -->
  </div>
  <input
    type="file"
    [name]="id"
    [id]="id"
    class="hidden"
    (change)="onFileSelected($event.target)"
    accept="image/*,.pdf"
    [formControlName]="formControlName"
    #fileUpload
  />
  <!-- If file exists -->
  <div class="" *ngIf="file" (click)="removeFile($event.target)">
    <div class="">
      <div class="">
        <strong class="text-sm">{{ inputLabel }}</strong>
        <span class="">{{ fileName }}</span>
      </div>
    </div>
    <!-- Delete Icon -->
  </div>
  <div
    class="error"
    *ngIf="fileSizeError || isInvalid"
    style="margin-bottom:10px;"
  >
    Please upload a file (max. 5MB)
  </div>
</ng-container>

For example you can look at here: https://stackblitz.com/edit/angular-ivy-we2x34

Upvotes: 3

Related Questions