Skip to content

ngneat/error-tailor

Repository files navigation


MIT commitizen PRs styled with prettier All Contributors ngneat spectator

Making sure your tailor-made error solution is seamless!

Getting Started

Run ng add @ngneat/error-tailor. This command updates the AppModule, and adds the ErrorTailorModule:

@NgModule({
  declarations: [AppComponent],
  imports: [
    ReactiveFormsModule,
    ErrorTailorModule.forRoot({
      errors: {
        useValue() {
          required: error => `This field is required`,
          minlength: ({ requiredLength, actualLength }) => 
                       `Expect ${requiredLength} but got ${actualLength}`,
          invalidAddress: error => `Address not valid`
        },
      }
    })
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

The errors config property takes a partial Provider that should provide an object with the form errors. Now, the only thing that you need to add is the errorTailor directive to your form:

<form [formGroup]="form" errorTailor>
  <div class="form-group">
    <input class="form-control" formControlName="name" placeholder="Name" />
  </div>

  <section formGroupName="address">
    <div class="form-group">
      <input class="form-control" formControlName="city" placeholder="City" />
    </div>

    <div class="form-group">
      <input class="form-control" formControlName="country" placeholder="Country" />
    </div>
  </section>

  <div class="form-group">
    <select formControlName="animal" class="form-control">
      <option *ngFor="let option of options; index as index" [ngValue]="option">
        {{ option.label }}
      </option>
    </select>
  </div>

  <button class="btn btn-success">Submit</button>
</form>
export class AppComponent {
  form: FormGroup;

  constructor(private builder: FormBuilder) {}

  ngOnInit() {
    this.form = this.builder.group({
      name: ['', [Validators.required, Validators.minLength(3)]],
      terms: [false, Validators.requiredTrue],
      animal: [null, Validators.required],
      address: this.builder.group(
        {
          city: ['', Validators.required],
          country: ['']
        },
        { validator: addressValidator }
      )
    });
  }
}

The directive will show each error automagically in two cases - on submit or on blur.

Inputs

  • controlErrorsClass - Custom class that'll be added to the control error component:
<input class="form-control" formControlName="city" placeholder="City" controlErrorsClass="my-class"/>
  • controlErrorsTpl - Custom error template:
<form errorTailor>
  <ng-template let-error let-text="text" #tpl> {{ error | json }} {{ text }} </ng-template>

  <div class="form-group">
    <input class="form-control" ngModel="name" required name="name" [controlErrorsTpl]="tpl" />
  </div>

  <button class="btn btn-success">Submit</button>
</form>
  • controlErrorAnchor - Provide an anchor element for the error component:
<div class="form-check form-group">
  <input type="checkbox" formControlName="terms" id="check" [controlErrorAnchor]="anchor" />
  <label class="form-check-label" for="check">
    I agree to the terms and conditions
  </label>
  <ng-template controlErrorAnchor #anchor="controlErrorAnchor"></ng-template>
</div>

Or:

<div class="form-check form-group" controlErrorAnchor>
  <input type="checkbox" formControlName="terms" id="check" />
  <label class="form-check-label" for="check">
    I agree to the terms and conditions
  </label>
</div>
  • customErrors - Local errors to use:
<input class="form-control" formControlName="city" placeholder="City" [customErrors]="serverErrors"/>

CSS Styling

The library adds a form-submitted to the submitted form. You can use it to style your inputs:

.form-submitted input.ng-invalid,
.form-submitted select.ng-invalid {
  border-color: #dc3545;
}

Config

  • blurPredicate - Elements that should listen the focusout event. The default predicate is:
{
  blurPredicate(element) {
    return element.tagName === 'INPUT';
  }
}

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Netanel Basal

πŸ’» πŸ“– πŸ€” πŸš‡

Toni Villena

πŸ’» ⚠️

This project follows the all-contributors specification. Contributions of any kind welcome!