自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证

     2023-03-13     15

关键词:

【中文标题】自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证【英文标题】:Custom angular2 form input component with two way binding and validation inside a component 【发布时间】:2016-04-21 01:10:03 【问题描述】:

有没有办法制作双向绑定输入组件,也可以在组件内部进行验证?

我想要实现的是拥有一个可以在我的表单中排列的组件,如下所示:

<form #f="ngForm">
            <my-form-input [(inputModel)]="name" [inputField]="myFormInputName"></my-form-input>
            <my-form-input [(inputModel)]="name2" [inputField]="myFormInputName2"></my-form-input>
...
            <my-form-input [(inputModel)]="lastItem" [inputField]="lastItemName"></my-form-input>

</form>

我有以下设置,但不知道如何正确设置:

组件:

import Component,Input, Output,EventEmitter from 'angular2/core'
import FORM_DIRECTIVES    from 'angular2/common';

@Component(
  selector: 'my-form-input',
  directives: [FORM_DIRECTIVES],
  template:
    `
    <input type="text" class="form-control"  id="i1" required [ngModel]="inputModel" (ngModelChange)="onChangeInput($event)" ngControl="ctrl" #ctrl="ngForm"/>
    <p>"Is field valid? I would like to make some decisions here depending on that: "+ctrl.valid</p>

  `
)
export class InputComponent 

  constructor();

  @Input()  inputField:string;
  @Input()  inputModel: Object;
  @Output() inputModelChange = new EventEmitter();

  onChangeInput(event)
    this.inputModel=event;
    this.inputModelChange.emit(event);
  

应用程序:

//our root app component
import Component from 'angular2/core'
import FORM_DIRECTIVES    from 'angular2/common';
import InputComponent from './my.input'


@Component(
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <p>Is there a way to make a custom 2 way binding form input component having also validation?</p>
      <form #f="ngForm">

        <my-form-input [(inputModel)]="name" [inputField]="myFormInputName"></my-form-input>

        <p>name</p>
      </form>
    </div>
  `,
  directives: [InputComponent,FORM_DIRECTIVES]
)
export class App 
  constructor() 
    this.name = 'Angular2'
  

我还做了一个 Plunker 来说明我的问题:http://plnkr.co/edit/0vXjHbQmv7v7EKQcLWaa?p=preview

【问题讨论】:

请注意,Angular 文档不鼓励在组件中进行用户输入验证:“我们的组件是服务的大消费者。它们依赖服务来处理大多数杂务。它们不从服务器获取数据,他们不验证用户输入,他们不直接登录到控制台。他们将这些任务委托给服务。” --Arch doc。我不确定我是否完全同意这一点,但我会让你知道。 【参考方案1】:

您可以将表单控件传递给您的组件,以便为输入创建一个专用控件。基于此新控件,当其valid 属性为false 时显示错误:

@Component(
  selector: 'my-form-input',
  directives: [FORM_DIRECTIVES],
  template: `
    <input type="text" class="form-control"  id="i1"   
       [ngModel]="inputModel"
       (ngModelChange)="onChangeInput($event)"
       [ngFormControl]="formCtrl.controls[inputField]"/>
    <p>Is field valid? I would like to make some decisions
       here depending on that: formCtrl.controls[inputField].valid
    </p>
  `
)
export class InputComponent implements OnInit 
  @Input()  inputField:string;
  @Input()  formCtrl;
  @Input()  inputModel: Object;
  @Output() inputModelChange = new EventEmitter(); 

  ngOnInit() 
    this.formCtrl.control.addControl(
        this.inputField, new Control('', Validators.required));
  

  onChangeInput(event)
    this.inputModel=event;
    this.inputModelChange.emit(event);
  

您需要使用addControl 方法使整个表单的状态与您在输入组件中创建的控件保持一致。

在您的情况下,您可以使用 ngControl 指令内联定义控件。我做了一些测试,但我无法让它以这种方式工作......

这是从父组件使用此组件的方法:

@Component(
  selector: 'my-app', 
  template: `
    <form #f="ngForm">
      <my-form-input [(inputModel)]="name" [inputField]="myFormInputName" [formCtrl]="f"></my-form-input>
    </form>
  `,
  directives: [ FORM_DIRECTIVES, InputComponent ]
)
export class AppComponent 

刚开始还是检查问题。表单的全局状态未更新,出现以下错误:

Expression '
    Valid : f.valid in AppComponent@1:24' has changed after it was checked. Previous value: '
    Valid : true'. Current value: '
    Valid : false'

要解决这个问题,请查看 Julien 基于 ChangeDetectorRef 类及其 detectChanges 方法的答案...

这是一个示例 plunkr:https://plnkr.co/edit/Z4uOUq2q4iXdpo0J6R1o?p=preview。

【讨论】:

确实有帮助。我对这个 enableProdMode 技巧有点困惑。什么情况下应该再次使用 enableDevMode?从 angular2 的角度来看是“DEV”还是从项目使用的角度来看是“DEV”? 我不认为启用 Prod 模式是解决此问题的正确方法...只是隐藏问题... 是的,你是对的。事实上,我会实现一个符合 ngForm / ngControl 的组件。请参阅此答案:***.com/questions/34948961/…。这样我们就不应该再遇到问题了,因为我们将参与整个表单验证生命周期... 如果有人在这里绊倒并想知道为什么它不适用于select,请仔细检查(ngModelChange) 是否绑定在select,而不是option【参考方案2】:

Thierry 的回答部分不错,因为在启用 ProdMode 时,您只是在隐藏问题:您没有刷新组件。

您必须在表单组件初始化后调用“detectChange”:

export class AppComponent 
    constructor(private cdr: ChangeDetectorRef) 
    ngOnInit() 
        this.cdr.detectChanges();
    

【讨论】:

感谢您指出这一点,朱利安!我相应地更新了我的答案的 plunkr 在这里找到了这个解决方案:***.com/questions/34364880/…

Angular 2 自定义表单输入

】Angular2自定义表单输入【英文标题】:Angular2customforminput【发布时间】:2016-04-2904:28:29【问题描述】:如何创建与原生&lt;input&gt;标签一样的自定义组件?我想让我的自定义表单控件能够支持ngControl、ngForm、[(ngModel)]。据我... 查看详情

如何在反应中使用自定义可重用组件作为输入字段

】如何在反应中使用自定义可重用组件作为输入字段【英文标题】:Howtousecustomresuablecomponentsasinputfieldsinreact【发布时间】:2021-09-1004:07:15【问题描述】:我在这里创建了一个可重用组件,该组件负责创建输入字段和标签。我想... 查看详情

如何在页面上多次重用自定义 Angular2 组件?

】如何在页面上多次重用自定义Angular2组件?【英文标题】:HowtoreuseacustomAngular2componentmultipletimeonapage?【发布时间】:2017-06-0507:30:23【问题描述】:我有一个名为employee的简单Angular2组件,它根据其属性的值填充并返回一个HTML模... 查看详情

自定义选择组件的Angular2变换模型

】自定义选择组件的Angular2变换模型【英文标题】:Angular2transformmodelforcustomselectComponent【发布时间】:2017-08-2008:05:02【问题描述】:在我的angular2应用程序中,我希望有一个可重用的选择组件,在初稿中,它看起来像这样:importC... 查看详情

Angular 2+将指令传递给自定义组件

】Angular2+将指令传递给自定义组件【英文标题】:Angular2+passdirectivestoacustomcomponent【发布时间】:2018-06-1401:25:49【问题描述】:我创建了一个自定义组件,它拥有自己的@input()、@output等等。该组件有一个&lt;input/&gt;字段,用... 查看详情

如何在表单中包含自定义组件?

】如何在表单中包含自定义组件?【英文标题】:Howtoincludeacustomcomponentinform?【发布时间】:2018-09-0319:31:25【问题描述】:我有一个名为“Employee-type”的组件(其中包括一个选择组件),它将用于显示相应的员工列表(数据网格... 查看详情

如何在 C# 2010 中以表单形式创建自定义组件?

】如何在C#2010中以表单形式创建自定义组件?【英文标题】:HowtocreatecustomcomponentinforminC#2010?【发布时间】:2011-08-3001:31:24【问题描述】:我想在C#中创建一个自定义组件,该自定义组件将充当仪表并由一个面板组成,其中包含... 查看详情

Angular2:使用自定义装饰器或注释将提供程序注入组件?

】Angular2:使用自定义装饰器或注释将提供程序注入组件?【英文标题】:Angular2:Injectingaproviderintoacomponentusingacustomdecoratororannotation?【发布时间】:2016-07-2716:03:13【问题描述】:我正在使用简单的TabsProvider为某些@Pages(Ionic2装饰... 查看详情

Angular2:例外:在控件上找不到指令注释

】Angular2:例外:在控件上找不到指令注释【英文标题】:Angular2:EXCEPTION:NoDirectiveannotationfoundonControl【发布时间】:2016-09-1115:39:39【问题描述】:我正在构建一个带有自定义验证的自定义输入字段组件,例如仅十进制数字、最小... 查看详情

包含一个组件作为 FormControl Angular2

】包含一个组件作为FormControlAngular2【英文标题】:IncludeacomponentasFormControlAngular2【发布时间】:2017-07-0910:31:52【问题描述】:我有一个通过表单生成器构建表单的组件,现在在该表单中我需要包含一个只有一个输入框作为表单控... 查看详情

自定义 joomla 组件的多个编辑表单

】自定义joomla组件的多个编辑表单【英文标题】:Multipleeditformsforcustomjoomlacomponent【发布时间】:2017-11-1510:46:15【问题描述】:按照Joomla上的文档创建自定义组件,并在论坛中进行搜索,我创建了几个带有菜单链接等的管理视图... 查看详情

vue表单控件绑定+自定义组件

...sp;   下拉列表演示     vue自定义组件组件放在components目录下组件基本要素:props $emit通过import导入自定义组件 制作一个倒计时组件:1、在conponents目录下,新建一个time.vue方法写在mouted声明周... 查看详情

angular2自定义弹出组件toast(使用路由)

参考技术A原理:使用Angular2的命名路由插座,一个用来显示app正常的使用,一个用来显示弹出框浏览器的导航栏中则这样显示路由配置toast内容创建用来跳转至popup路由的服务,例如popup.service使用:一、在app.module.ts中将服务导进... 查看详情

Angular2 2方式绑定中同名的自定义输入和输出

】Angular22方式绑定中同名的自定义输入和输出【英文标题】:CustominputandoutputonsamenameinAngular22waybinding【发布时间】:2016-10-1717:26:03【问题描述】:我知道如何修复我的组件,为此组件的输出值使用不同的名称。让我分享我的代码... 查看详情

自定义组件不会使其成为组件

】自定义组件不会使其成为组件【英文标题】:customcomponentdoesnotmakesitintocomponents【发布时间】:2015-03-0701:50:53【问题描述】:我有一个在winforms中使用的自定义组件,效果很好。只有一个小问题,当我将它放在表单上时,设计师... 查看详情

具有自定义属性表单的 ASP.NET 组件

】具有自定义属性表单的ASP.NET组件【英文标题】:ASP.NETComponentwithcustompropertyform【发布时间】:2011-06-2916:10:33【问题描述】:我正在开发一个供内部使用的自定义DataGridView控件,并且我想添加一个自定义属性选项,它会在其中启... 查看详情

Angular 2:包含子组件的表单

】Angular2:包含子组件的表单【英文标题】:Angular2:Formcontainingchildcomponent【发布时间】:2017-03-0312:09:45【问题描述】:我有一个组件,它有一个表单和表单内的一些子组件。子组件是使用*ngFor创建的,每个子组件都包含input元素... 查看详情

Vue:从自定义组件派生的自定义组件中的 v-model 和输入事件

】Vue:从自定义组件派生的自定义组件中的v-model和输入事件【英文标题】:Vue:v-modelandinputeventincustomcomponentderivedofacustomcomponent【发布时间】:2018-10-0323:51:09【问题描述】:我有一个自定义输入,我在其中接收一个值道具并在输... 查看详情