typescript – Angular 2自定义表单输入

前端之家收集整理的这篇文章主要介绍了typescript – Angular 2自定义表单输入前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如何创建自定义组件,它将像本机< input>标签?我想让我的自定义表单控件能够支持ngControl,ngForm,[(ngModel)]。

根据我的理解,我需要实现一些接口,使我自己的表单控件工作,就像本机一样。

另外,似乎ngForm指令只绑定< input>标签,是这样吗?我怎么能处理呢?

让我解释一下为什么我需要这个。我想包装几个输入元素,使他们能够一起工作作为一个单一的输入。还有其他办法来处理吗?
再一次:我想让这个控件就像本机一样。验证,ngForm,ngModel双向绑定等。有任何想法吗?

ps:我使用Typescript。

ps:对不起英语:/

事实上,有两件事要实现:

>提供表单组件逻辑的组件。它不是一个输入,因为它将由ngModel本身提供
>一个自定义的ControlValueAccessor,它将实现这个组件和ngModel / ngControl之间的桥梁

让我们举个例子。我想实现一个管理公司标签列表的组件。组件将允许添加删除标签。我想添加一个验证,以确保标签列表不为空。我将在我的组件中定义它如下所述:

(...)
import {TagsComponent} from './app.tags.ngform';
import {TagsValueAccessor} from './app.tags.ngform.accessor';

function notEmpty(control) {
  if(control.value == null || control.value.length===0) {
    return {
      notEmpty: true
    }
  }

  return null;
}

@Component({
  selector: 'company-details',directives: [ FormFieldComponent,TagsComponent,TagsValueAccessor ],template: `
    <form [ngFormModel]="companyForm">
      Name: <input [(ngModel)]="company.name"
         [ngFormControl]="companyForm.controls.name"/>
      Tags: <tags [(ngModel)]="company.tags" 
         [ngFormControl]="companyForm.controls.tags"></tags>
    </form>
  `
})
export class DetailsComponent implements OnInit {
  constructor(_builder:FormBuilder) {
    this.company = new Company('companyid','some name',[ 'tag1','tag2' ]);
    this.companyForm = _builder.group({
       name: ['',Validators.required],tags: ['',notEmpty]
    });
  }
}

TagsComponent组件定义了在标签列表中添加删除元素的逻辑。

@Component({
  selector: 'tags',template: `
    <div *ngIf="tags">
      <span *ngFor="#tag of tags" style="font-size:14px"
         class="label label-default" (click)="removeTag(tag)">
        {{label}} <span class="glyphicon glyphicon-remove"
                        aria-  hidden="true"></span>
      </span>
      <span>&nbsp;|&nbsp;</span>
      <span style="display:inline-block;">
        <input [(ngModel)]="tagToAdd"
           style="width: 50px; font-size: 14px;" class="custom"/>
        <em class="glyphicon glyphicon-ok" aria-hidden="true" 
            (click)="addTag(tagToAdd)"></em>
      </span>
    </div>
  `
})
export class TagsComponent {
  @Output()
  tagsChange: EventEmitter;

  constructor() {
    this.tagsChange = new EventEmitter();
  }

  setValue(value) {
    this.tags = value;
  }

  removeLabel(tag:string) {
    var index = this.tags.indexOf(tag,0);
    if (index != undefined) {
      this.tags.splice(index,1);
      this.tagsChange.emit(this.tags);
    }
  }

  addLabel(label:string) {
    this.tags.push(this.tagToAdd);
    this.tagsChange.emit(this.tags);
    this.tagToAdd = '';
  }
}

正如你可以看到的,这个组件中没有输入,但是有一个setValue输入(名称在这里不重要)。我们稍后使用它提供从ngModel到组件的值。此组件定义在组件的状态(标签列表)更新时要通知的事件。

让我们现在实现这个组件和ngModel / ngControl之间的链接。这对应于实现ControlValueAccessor接口的指令。必须针对NG_VALUE_ACCESSOR令牌为此值访问器定义提供程序(不要忘记使用forwardRef,因为之后定义了该指令)。

指令将在主机的tagsChange事件(即指令附加到的组件,即TagComponent)上附加事件监听器。当事件发生时,将调用onChange方法。此方法对应于由Angular2注册方法。这样,它将知道更改并相应地更新相关的表单控件。

当在ngForm中绑定的值被更新时,writeValue被调用。在注入了附加的组件(即TagsComponent)之后,我们将能够调用它来传递这个值(参见前面的setValue方法)。

不要忘记在指令的绑定中提供CUSTOM_VALUE_ACCESSOR。

这里是自定义ControlValueAccessor的完整代码

import {TagsComponent} from './app.tags.ngform';

const CUSTOM_VALUE_ACCESSOR = CONST_EXPR(new Provider(
  NG_VALUE_ACCESSOR,{useExisting: forwardRef(() => TagsValueAccessor),multi: true}));

@Directive({
  selector: 'tags',host: {'(tagsChange)': 'onChange($event)'},providers: [CUSTOM_VALUE_ACCESSOR]
})
export class TagsValueAccessor implements ControlValueAccessor {
  onChange = (_) => {};
  onTouched = () => {};

  constructor(private host: TagsComponent) { }

  writeValue(value: any): void {
    this.host.setValue(value);
  }

  registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
  registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}

这样当我删除公司的所有标签时,companyForm.controls.tags控件的valid属性自动变为false。

有关更多详细信息,请参阅本文(“NgModel兼容组件”一节)

> http://restlet.com/blog/2016/02/17/implementing-angular2-forms-beyond-basics-part-2/

猜你在找的Angularjs相关文章