angular 4 own form element component

放肆的年华 提交于 2019-12-06 14:54:03

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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!