讓angular表單更簡單

extend 組件的使用

公共的方法,屬性

@Component({
  selector: 'app-three',
  templateUrl: './three.component.html',
})
export class ThreeComponent {
  @Input() two = 'bbb';
  @Input() three = 'ccc';

  createMethod(val: any) {
    console.log(val);
  }
}

父組件繼承, 跟html 沒有關係

export class TwoComponent extends ThreeComponent implements OnInit {
  @Input('one') one: string = 'aaa'
  ngOnInit(): void {
  }
}

html

<div>{{one}}</div>
<div>{{two}}</div>
<div>{{three}}</div>
<button (click)="createMethod('xxx')">CLICK</button>

我們可以把公共的方法和屬性寫成一個組件, 然後其他組件需要這部分繼承

自定義指令擴展UI組件

@Directive({
  // 組件
  selector: 'p-calendar',
  // 包含某個指令
  selector: 'p-calendar[defaultCalendar]',
  // 某個指令 排除某個指令
  selector: 'p-calendar:not([resetCalendar])',
})

我們寫個ng-zorro的日期選擇器

<nz-date-picker [(ngModel)]="date"
                nzFormat="yyyy/MM/dd HH:mm:ss"
                [nzShowTime]="false" [nzShowNow]="false"
                [nzShowToday]="false" [nzAllowClear]="false" [nzBorderless]="true"></nz-date-picker>

我們發現上面的屬性太多了,我們可以通過自定義指令執行處理

@Directive({
  selector: 'nz-date-picker[appDateDefault]'
})
export class DateDefaultDirective {

  constructor(private defaultDate: NzDatePickerComponent) {
    this.defaultDate.nzBorderless = true;
    this.defaultDate.nzAllowClear = false;
    this.defaultDate.nzShowToday = false;
    this.defaultDate.nzShowNow = false;
    this.defaultDate.nzShowTime= false;
  }
}
<nz-date-picker [(ngModel)]="date" nzFormat="yyyy/MM/dd HH:mm:ss" appDateDefault></nz-date-picker>

當我們需要對項目的90%以上添加這個指令, 可以設置排除某個屬性

@Directive({
  selector: 'nz-date-picker:not([appDateDefault])'
})

只要組件中不設置 appDateDefault 某符合, 類似於默認不寫,也是符合要求的, 可用於修改組件的默認設置, 在這裏基礎上修復bug

指令修改子組件的表單

有時候我們糾結, 父組件修改子組件表單的信息, 我們看到常規來做,我們傳入一個參數,然後做各種判斷處理, 導致子組件的代碼很累贅

@Component({
  selector: 'person',
  template: `
    <div [formGroup]="form">
      <div>
        <label>Name</label>
        <input type="text" formControlName="name" />
      </div>

      <div>
        <label>Contact info</label>
        <input type="text" formControlName="contactInfo" />
      </div>

      <div>
        <label>Allergies</label>
        <input type="text" formControlName="allergies" />
      </div>

      <strong>{{ form.valid ? 'valid' : 'invalid' }}</strong>
    </div>
  `,
})
export class PersonComponent {
  form = this.formBuilder.group({
    name: ['', Validators.required],
    contactInfo: [''],
    allergies: [''],
  })

  constructor(private formBuilder: FormBuilder) {}
}

給父級添加一個指令

@Directive({
  selector: 'person[stage-one]',
})
export class StageOneDirective {
  constructor(host: PersonComponent) {
    host.form.get('contactInfo').setValidators([Validators.required])
  }
}

添加另一個添加

@Directive({
  selector: 'person[stage-one]',
})
export class StageOneDirective {
  constructor(host: PersonComponent) {
    host.form.get('contactInfo').setValidators([Validators.required])
  }
}

然後使用的時候

<person></person>

<person stage-one></person>

<person stage-two></person>

自定義指令校驗讓Form表單更簡單

校驗器

import {Directive, Input} from '@angular/core';
import {AbstractControl, NG_VALIDATORS, ValidationErrors} from "@angular/forms";

@Directive({
  selector: '[appValidator]',
  providers: [{provide: NG_VALIDATORS, useExisting: ValidatorDirective, multi: true}],
})
export class ValidatorDirective {
  @Input() appValidator!: (control: AbstractControl) => ValidationErrors | null;

  validate(control: AbstractControl): ValidationErrors | null {
    return this.appValidator(control);
  }
}

組件

<input type="text" [appValidator]="scoreValidator" [(ngModel)]="date" #score="ngModel"/>
<app-has-error [control]="score.control"></app-has-error>
export class TwoComponent implements OnInit {
  date = null
  scoreValidator = (control: AbstractControl): ValidationErrors | null => {
    const {dirty, touched, value} = control;
    // 這個是爲了默認默認的時候觸發
    if ((!!dirty || !!touched) && !value) {
      return {required: true}
    }
    if (value?.length > 10) {
      return {maxScore: 10};
    }
    return null;
  };
}

app-has-error

  @Input() control!: AbstractControl

這樣我就可以做一些報錯處理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章