簡體   English   中英

模板驅動的表單如何訪問組件內的控件?

[英]How can a template-driven form access a control inside a component?

我有一個使用模板驅動方法的<form>

該表單包含各種原生控件,如<input><select> ,以及包含原生<input>元素的包裝組件,如<text-control><checkbox-control>

表單如何訪問<text-control>的本機元素以讀取其錯誤和觸摸狀態?

另外,如果我想在該包裝器組件上放置一個驗證器指令並將其向下傳遞到本機<input> ,我該如何處理?

我嘗試在包裝器組件上使用ngModel ,但它不起作用,因為ngModel掛鈎到包裝器組件,而不是底層的<input>元素。

另一種方法是使用<ng-content> ,但是底層的原生元素需要很多屬性,以至於到處復制粘貼它會很痛苦。

例子:

<checkbox-control>
  <!-- Now, it's easy for the form to access the control. -->
  <!-- But I've too many attributes and properties that go here. -->
  <input type="checkbox">
</checkbox-control>

PS:我不打算使用 ElementRef 來訪問原生元素,我只是想讓<form>知道原生元素的錯誤狀態,這樣我就可以判斷表單是否有效。

例子:

<form #editor="ngForm">
  <input type="text" validateText />

  <select validateSelect>
    <option value="1"></option>
    <option value="2"></option>
  </select>

  <!-- Does not work. -->
  <checkbox-control validateCheckbox></checkbox-control>
</form>

提前致謝。

您可以在模板方法中使用元素的本地引用。 請參考我剛剛寫的這段代碼來解釋:

https://stackblitz.com/edit/angular-ivy-7no9ok?file=src/app/app.component.html

我找到了一個合理的解決方案,無需編寫太多代碼,也無需編輯太多組件。

第 1 步:創建您的驗證器

@Directive({ selector: '[assertNoSpecialChars]' })
export class SpecialCharacterValidator implements Validator {
  // The directive will have a reference for the name of the form's control.
  @Input() assertNoSpecialChars: string = '';

  validate(group: FormGroup): ValidationErrors | null {
    const control = group.controls[this.assertNoSpecialChars];

    // For simplicity, let's say we don't want the dollar sign in our input.
    if (control.value.includes('$')) {
      return { invalid: true };
    } else {
      return null;
    }
  }
}

第 2 步:在表單上應用指令

<form #f="ngForm" [assertNoSpecialChars]="'username'">
  <text-control></text-control>
</form>

第 3 步:將組件的輸入事件綁定到托管表單組件

<form #f="ngForm" [assertNoSpecialChars]="'username'">
  <text-control (input)="updateFormManually($event, 'username')"></text-control>
</form>

第 4 步:獲取 NgForm 的引用,並實現更新機制

@Component({})
export class FormComponent implements AfterViewInit {
  // Grab a reference for your NgForm.
  @ViewChild('f', { static: true }) f!: NgForm;

  // Create your form control.
  username: FormControl = new FormControl();

  // Register your control to the NgForm.
  ngAfterViewInit(): void {
    this.f.form.addControl('username', this.username);
  }

  // Update the control manually.
  updateFormManually(event: any, controlName: string): void {
    this.f.form.controls[controlName].setValue(event.target.value);
  }
}

現在,表單的有效性狀態和錯誤消息將被正確綁定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM