重用单个 Angular 5 反应形式元素 [英] Reuse individual Angular 5 reactive form elements

查看:22
本文介绍了重用单个 Angular 5 反应形式元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍在学习 Angular 5,并且已经开始使用反应式"表单模型.但是,我能找到的几乎每个示例和教程都让您在一个模板中创建整个表单.通常在 AngularJS 1.x 中,我们会将每个字段存储在自己的指令中,然后将它们连接在一起以创建一个表单以减少重复.

有没有办法只使用一个文件并包含模板和所有验证的 Angular 5 反应式表单来做到这一点?我可以看到如何分两部分来完成,其中我将有一个包含表单元素 HTML、验证消息等的组件,但您还需要在完整表单的组件中创建 FormControl 并为其指定默认值和验证.

也许这非常普遍,我只是没有正确搜索它,但是如果有人可以向我指出任何模式、教程或帮助,我将不胜感激,因为我觉得这是我的表单中缺少的最后一块.谢谢!

解决方案

万一其他人遇到这个问题,我能找到的最佳答案(并且至少被许多其他开发人员使用,即使不是最好的实践)是在父主表单"组件中创建一个 FormGroup,然后创建一个新的 FormControl 并将其附加到该 FormGroup.例如,这里是可重用表单控件的组件:

import {Component, OnInit, Input} from '@angular/core';从@angular/forms"导入 {FormControl、FormGroup、Validators};@成分({选择器:'app-project-length',templateUrl: './project-length.component.html',styleUrls: ['./project-length.component.css']})导出类 ProjectLengthComponent 实现 OnInit {@Input() isFormSubmitted: 布尔值;@Input() projectForm: FormGroup;构造函数(){}ngOnInit() {this.projectForm.addControl('projectLength', new FormControl(0, [Validators.required, this.hasCorrectLength]));}hasCorrectLength(control: FormControl): {[s: string]: boolean} {const 长度:数字 = control.value;如果(长度<2||长度>10){返回{'不正确的长度':真};}返回空;}}

这是该表单元素组件的模板:

<label for="project-length">项目长度</label><输入类=形式控制"类型=数字"id="项目长度"placeholder="输入项目长度"表单控件名称=项目长度"/><span class="help-block"*ngIf="!projectForm.controls['projectLength'].valid && (projectForm.controls['projectLength'].touched || isFormSubmitted)">请输入 2 到 9 之间的项目长度</span>

这是父表单的组件(它已经有一些我正在研究的教程中的内置表单元素,并且只有一个可重用的表单元素组件):

import { Component, OnInit } from '@angular/core';从@angular/forms"导入 {FormControl、FormGroup、Validators};从'../shared/Status'导入{状态};@成分({选择器:'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css']})导出类 AppComponent 实现 OnInit{项目表格:表格组;状态:数组<状态>= [{id: 1, name: 'Critical'},{id:2,名称:'稳定'},{id: 3, name: '完成'}];表单提交:boolean = false;ngOnInit() {this.projectForm = new FormGroup({namey: new FormControl(null, [Validators.required, this.cannotBeTest1]),电子邮件:新 FormControl(null, [Validators.required, Validators.email]),状态:new FormControl('1')});}提交(){console.log(this.projectForm);this.formSubmitted = true;如果(this.projectForm.valid){console.log('表单数据:');console.log(this.projectForm);}}cannotBeTest1(control: FormControl): {[s: string]: boolean} {...}}

以下是主要表单组件模板的重要部分:

<div class="row"><div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2"><form class="ui form-vertical" [formGroup]="projectForm" (ngSubmit)="onSubmit()">...<app-project-length [projectForm]="projectForm" [isFormSubmitted]="formSubmitted"></app-project-length>...

I am still learning Angular 5 and have started working with the "reactive" form model. However, almost every example and tutorial I can find has you creating the entire form in one template. Normally in AngularJS 1.x, we would store each field in its own directive and then wire them together to create a form to cut down on duplication.

Is there a way to do this with Angular 5 reactive forms using only one file and having the template and all validations included? I can see how to do it in two pieces, where I would have a component that contains the form element HTML, validation messages, etc. but then you also need to create the FormControl in the full form's component and give it its default value and validations.

Maybe this is extremely common and I am just not searching for it correctly, but if anyone can point me towards any patterns, tutorials or help I would greatly appreciate it as I feel it is the last piece I am missing for my forms. Thank you!

解决方案

In case anyone else comes across this, the best answer I could find (and which is at least used by many other devs out there, even if not a best practice) is to create a FormGroup in the parent "main form" component and then create and attach a new FormControl to that FormGroup. For example, here is the component for the re-usable form control:

import {Component, OnInit, Input} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';

@Component({
  selector: 'app-project-length',
  templateUrl: './project-length.component.html',
  styleUrls: ['./project-length.component.css']
})
export class ProjectLengthComponent implements OnInit {

 @Input() isFormSubmitted: boolean;
 @Input() projectForm: FormGroup;

 constructor() {
 }

 ngOnInit() {
 this.projectForm.addControl('projectLength', new FormControl(0, [Validators.required, this.hasCorrectLength]));
 }

 hasCorrectLength(control: FormControl): {[s: string]: boolean} {
   const length: number = control.value;
  if (length < 2 || length > 10) {
    return { 'incorrectLength' : true };
  }
  return null;
}

}

Here is the template for that form element component:

<div class="form-group" [formGroup]="projectForm">
<label for="project-length">project length</label>
<input
  class="form-control"
  type="number"
  id="project-length"
  placeholder="Enter project length"
  formControlName="projectLength"
/>
<span class="help-block" 
  *ngIf="!projectForm.controls['projectLength'].valid && (projectForm.controls['projectLength'].touched || isFormSubmitted)">
    please enter a project length between 2 and 9
</span>

Here is the component of the parent form (which already has some built-in form elements from a tutorial I was working on, and only one re-usable form element component):

import { Component, OnInit } from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import { Status} from '../shared/Status';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  projectForm: FormGroup;
  statuses: Array<Status> = [
    {id: 1, name: 'Critical'},
    {id: 2, name: 'Stable'},
    {id: 3, name: 'Finished'}
  ];
  formSubmitted: boolean = false;

  ngOnInit() {
    this.projectForm = new FormGroup({
      namey: new FormControl(null, [Validators.required, this.cannotBeTest1]),
      email: new FormControl(null, [Validators.required, Validators.email]),
      status: new FormControl('1')
    });
  }

  onSubmit() {
    console.log(this.projectForm);

    this.formSubmitted = true;
    if (this.projectForm.valid) {
    console.log('Form data:');
    console.log(this.projectForm);
  }
}
cannotBeTest1(control: FormControl): {[s: string]: boolean} {
  ...
}
}

And here are the important parts of the template for the main form component:

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
      <form class="ui form-vertical" [formGroup]="projectForm" (ngSubmit)="onSubmit()">
        ...
        <app-project-length [projectForm]="projectForm" [isFormSubmitted]="formSubmitted"></app-project-length>
        ...

这篇关于重用单个 Angular 5 反应形式元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆