创建一个可重用的FormGroup

创建一个可重用的FormGroup

本文介绍了创建一个可重用的FormGroup的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道创建自定义控件作为组件,但是我不知道如何创建自定义.

I am aware of creating custom controls as components, but I can't figure out how to create custom groups.

我们可以通过实现ControlValueAccessor 并使用诸如<my-cmp formControlName="foo"></my-cmp>,如何为一个 达到这种效果?

The same we can do this by implementing ControlValueAccessor and using a custom component like <my-cmp formControlName="foo"></my-cmp>, how can we achieve this effect for a group?

<my-cmp formGroupName="aGroup"></my-cmp>

两个非常常见的用例是(a)将长格式分成多个步骤,每个步骤都放在一个单独的组件中;(b)封装一组以多种形式出现的字段,例如地址(国家/地区,州,城市,地址,门牌号)或出生日期(年,月,日).

Two very common use-cases would be (a) separting a long form into steps, each step in a separate component and (b) encapsulating a group of fields which appear across multiple forms, such as address (group of country, state, city, address, building number) or date of birth (year, month, date).

父母的以下表单是使用 FormBuilder 构建的:

Parent has the following form built with FormBuilder:

// parent model
form = this.fb.group({
  username: '',
  fullName: '',
  password: '',
  address: this.fb.group({
    country: '',
    state: '',
    city: '',
    street: '',
    building: '',
  })
})

父模板(为简洁起见,它是不可访问的和非语义的):

Parent template (inaccessible and non-semantic for brevity):

<!-- parent template -->
<form [groupName]="form">
  <input formControlName="username">
  <input formControlName="fullName">
  <input formControlName="password">
  <address-form-group formGroup="address"></address-form-group>
</form>

现在,此AddressFormGroupComponent知道如何处理内部具有这些特定控件的组.

Now this AddressFormGroupComponent knows how to handle a group which has these specific controls inside of it.

<!-- child template -->
<input formControlName="country">
<input formControlName="state">
<input formControlName="city">
<input formControlName="street">
<input formControlName="building">

推荐答案

rusev的答案,这就是注入 ControlContainer .

结果表明,如果将formGroupName放置在组件上,并且该组件注入ControlContainer,则会获得对包含该表单的容器的引用.从这里很容易.

Turns out that if you place formGroupName on a component, and if that component injects ControlContainer, you get a reference to the container which contains that form. It's easy from here.

我们创建一个子表单组件.

We create a sub-form component.

@Component({
  selector: 'sub-form',
  template: `
    <ng-container [formGroup]="controlContainer.control">
      <input type=text formControlName=foo>
      <input type=text formControlName=bar>
    </ng-container>
  `,
})
export class SubFormComponent {
  constructor(public controlContainer: ControlContainer) {
  }
}

请注意我们如何需要输入包装.我们不需要表单,因为它已经在表单中了.因此,我们使用ng-container.这将与最终DOM分离,因此没有不必要的元素.

Notice how we need a wrapper for the inputs. We don't want a form because this will already be inside a form. So we use an ng-container. This will be striped away from the final DOM so there's no unnecessary element.

现在我们可以使用此组件.

Now we can just use this component.

@Component({
  selector: 'my-app',
  template: `
    <form [formGroup]=form>
      <sub-form formGroupName=group></sub-form>
      <input type=text formControlName=baz>
    </form>
  `,
})
export class AppComponent  {
  form = this.fb.group({
    group: this.fb.group({
      foo: 'foo',
      bar: 'bar',
    }),
    baz: 'baz',
  })

  constructor(private fb: FormBuilder) {}
}

您可以看到实时演示 >在StackBlitz上.

You can see a live demo on StackBlitz.

这是在某些方面对rusev的回答的改进:

This is an improvement over rusev's answer in a few aspects:

  • 无自定义groupName输入;相反,我们使用Angular提供的formGroupName
  • 不需要@SkipSelf装饰器,因为我们不是 注入父控件,而是我们需要的
  • 没有尴尬的group.control.get(groupName)会为了获取自己而交给父母.
  • no custom groupName input; instead we use the formGroupName provided by Angular
  • no need for @SkipSelf decorator, since we're not injecting the parent control, but the one we need
  • no awkward group.control.get(groupName) which is going to the parent in order to grab itself.

这篇关于创建一个可重用的FormGroup的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 02:51