角度4自己的表单元素组件 [英] angular 4 own form element component

查看:100
本文介绍了角度4自己的表单元素组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是angular的初学者,在这件事上可能需要一点帮助.首先,我将展示它如何工作,然后写出我希望它如何工作.

这是使用ngModel时的常规方法:

 < form><输入名称=名称"占位符=名称" [(ngModel)] ="model.name" value ="/>< select name ="select" [(ngModel)] ="model.select">< option value ="1"> ..</option>...</select><输入type ="button" value =点击我"/></form> 

如果您不希望自己的选择出现,这已经足够了.我的目的是为此创建一个组件,在其中可以创建div和其他可以设计成适合该表单元素将来显示的内容.另一方面,我想保持ngModel的舒适性.因此,根据我的目标,模板应如下所示:

 < form><输入名称=名称"占位符=名称" [(ngModel)] ="model.name" value ="/>< app-select label ="label" name ="select" [placeholder] ='placeholder'" [(ngModel)] ="select" [options] ="options"></app-select><输入type ="button" value =单击我"/></form> 

我已经尝试创建类似这样的东西,但是我失败了,可悲的是:(可以给有更多经验的人帮助我吗?谢谢您的时间和事先的答复!

如有必要,我可以重新创建一些最小的内容: https://stackblitz.com/

解决方案

以下是我如何将此表单创建为表单(请记住,我是通过表单生成器使用反应性表单,而不是通过ngModel使用模板驱动的表单):

首先,我在名为 forms 的目录中创建一个自定义FormModule.

下一步,在其中,我有各种表单组件.让我们以 LoginFormComponent 为例.

这是 LoginFormComponent :

  import'@ angular/core'中的{组件,OnInit,输入,输出,EventEmitter};从'@ angular/forms'导入{FormBuilder,FormGroup,Validators};@零件({选择器:登录表单",templateUrl:"./login-form.component.html"})导出类LoginFormComponent实现OnInit {@Output()onChange:EventEmitter< FormGroup>=新的EventEmitter();形式:FormGroup;构造函数(私有fb:FormBuilder){this.form = this.fb.group({电子邮件:[null,Validators.email],密码:[null,[Validators.required,Validators.minLength(6),Validators.maxLength(60)]]});this.form.valueChanges.subscribe(()=> this.onChange.emit(this.form));}ngOnInit(){this.onChange.emit(this.form);}} 

这是HTML:

 < form autocomplete ="off" [formGroup] ="form">< div class ="form-group">< label for =用户名">电子邮件*</label><输入type ="text" id =用户名" class ="form-control"占位符=输入您的电子邮件地址" formControlName =电子邮件" autofocus>< control-messages [control] ="form.get('email')"<//control-messages></div>< label for ="password">密码*</label><输入type ="password" id ="password" class ="form-control"占位符=输入密码" formControlName =密码">< control-messages [control] ="form.get('password')" [label] ='Password'"></control-messages></form> 

现在,在导入 FormModule 的模块内的任何自定义组件中,我都可以执行以下操作:

app.component.html:

 <登录表单(onChange)="form = $ event"></登录表单>< button(click)="submit()"> Submit</button> 

app.component.ts:

  @Component({...})导出类AppComponent {形式:FormGroup;提交() {//使用`this.form`进行操作.}} 

这种设计的好处可能不会立即显现出来,但是它使我们能够做一些事情:

  1. 首先,只要我们导入自定义的 FormModule ,就可以在应用程序中的任何地方重复使用 login-form 组件.如果我们更改它,它将在所有地方自动更新.使事物保持干燥.
  2. 接下来,我们可能不希望在每个地方都使用相同的提交按钮/文本,我们可能希望它在不同的位置执行不同的操作,因此 login-form 组件仅包含表单本身,并且任何提交逻辑都在其外部进行处理以提高重用能力.当您具有用于创建和编辑的表单时,这很重要.编辑时的按钮可以保存数据,创建时的按钮可以创建新内容.如果将提交"按钮放在表单组件内部,则这种重用不容易实现.

对于稍微复杂的表单,例如可以接受一些默认值的表单,请看下面的示例 TagFormComponent :

  import'@ angular/core'中的{组件,OnInit,输入,输出,EventEmitter};从'@ angular/forms'导入{FormBuilder,FormGroup,Validators};从共享"导入{标签};@零件({选择器:标签形式",templateUrl:"./tag-form.component.html"})导出类TagFormComponent实现OnInit {@Output()onChange:EventEmitter< FormGroup>=新的EventEmitter();形式:FormGroup;构造函数(私有fb:FormBuilder){this.form = this.fb.group({名称:[null,Validators.email]});this.form.valueChanges.subscribe(()=> {this.onChange.emit(this.form);});}@输入()设置标签(标签:标签){如果(标签){this.form.patchValue(tag);}}ngOnInit(){this.onChange.emit(this.form);}} 

此代码与 LoginFormComponent 相同,但可以为表单传递一些默认值.像这样:

 < tag-form [tag] ="tag"(onChange)="form = $ event"></tag-form> 

I am beginner in angular and I may need a little help with this thing. First of all I will just show how could it work then I will write about how I want it to work.

This is the regular way when you work with ngModel:

    <form>
      <input name="name" placeholder="name" [(ngModel)]="model.name" value="" />
      <select name="select" [(ngModel)]="model.select">
         <option value="1">..</option>
         ...
      </select>
      <input type="button" value=" click me" />
    </form>

This is good enough if you don't want an own appearance for the select. My aim is to create a component for this where I can create divs and other contents that I can design to fit to the future display of this form element. On the other hand I want to keep the comfort of the ngModel. So the template should look like this in my aim:

    <form>
      <input name="name" placeholder="name" [(ngModel)]="model.name" value="" />
      <app-select label="label" name="select" [placeholder]="'placeholder'" [(ngModel)]="select" [options]="options"></app-select >
      <input type="button" value=" click me" />
    </form>

I already tried to create something like this but I have failed, sadly :( Could some who has more experience then me help me with this please? Thanks your time and answers in advance!

I can recreate something minimal if necessary here: https://stackblitz.com/

解决方案

Here is how I do this form my forms (keep in mind I am using reactive forms with the form builder, not template driven forms with ngModel):

First, I create a custom FormModule in a directory called forms.

Next, inside there I have various form components. Let's use the LoginFormComponent for example.

Here is the LoginFormComponent:

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

@Component({
    selector: 'login-form',
    templateUrl: './login-form.component.html'
})
export class LoginFormComponent implements OnInit {
    @Output() onChange: EventEmitter<FormGroup> = new EventEmitter();

    form: FormGroup;

    constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
            email: [null, Validators.email],
            password: [null, [Validators.required, Validators.minLength(6), Validators.maxLength(60)]]
        });

        this.form.valueChanges.subscribe(() => this.onChange.emit(this.form));
    }

    ngOnInit() {
        this.onChange.emit(this.form);
    }
}

Here is the HTML:

<form autocomplete="off" [formGroup]="form">
    <div class="form-group">
        <label for="username">Email *</label>
        <input type="text" id="username" class="form-control" placeholder="Enter your email address" formControlName="email" autofocus>
        <control-messages [control]="form.get('email')"></control-messages>
    </div>

    <label for="password">Password *</label>
    <input type="password" id="password" class="form-control" placeholder="Enter your password" formControlName="password">
    <control-messages [control]="form.get('password')" [label]="'Password'"></control-messages>
</form>

Now in any custom component that is within a module that imports FormModule, I can do the following:

app.component.html:

<login-form (onChange)="form = $event"></login-form>

<button (click)="submit()">Submit</button>

app.component.ts:

@Component({...})
export class AppComponent {
    form: FormGroup;

    submit() {
        // Do something with `this.form`.
    }
}

The benefit of this sort of design may not be super obvious right away, but it enables us to do a few things:

  1. First, we can re-use the login-form component anywhere in our app as long as we import our custom FormModule. Any if we change it, it will be updated everywhere automatically. Keeps things DRY.
  2. Next, we may not want the same submit button/text every where, and we may want it to do different things in different locations, so the login-form component only contains the form itself, and any submission logic is handled outside of it for reuse-ability. This matters when you have forms that are used for both creation and editing. The button on edit can save data, where as the button on create can create something new. If you put the submit button inside the form component, this reuse isn't easily feasible.

For slightly more complex forms, say a form that can take in some default values, take a look at this example TagFormComponent:

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

import { Tag } from 'shared';

@Component({
    selector: 'tag-form',
    templateUrl: './tag-form.component.html'
})
export class TagFormComponent implements OnInit {
    @Output() onChange: EventEmitter<FormGroup> = new EventEmitter();

    form: FormGroup;

    constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
            name: [null, Validators.email]
        });

        this.form.valueChanges.subscribe(() => {
            this.onChange.emit(this.form);
        });
    }

    @Input()
    set tag(tag: Tag) {
        if (tag) {
            this.form.patchValue(tag);
        }
    }

    ngOnInit() {
        this.onChange.emit(this.form);
    }
}

This one follows the same general idea as the LoginFormComponent, except this one can pass in some default values for the form. Like this:

<tag-form [tag]="tag" (onChange)="form = $event"></tag-form>

这篇关于角度4自己的表单元素组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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