如何在Angular 2/4中创建通用控件? [英] How can i create a common control in Angular 2/4?

查看:93
本文介绍了如何在Angular 2/4中创建通用控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须创建一个control/template/common html,它将有一个下拉列表.这个通用控件将调用我的数据服务,并将此下拉列表与数据绑定.

I have to create a control/template/common html which will have a drop down. This common control will call my data service and bind this drop down with data.

我可以创建一个组件并将其HTML下拉,然后在我所有的父组件中调用该组件的选择器.但是,我想要的是我需要将密钥传递给该通用控件,并且该密钥将被发送到服务,服务将仅提供匹配的记录,并且根据这些记录,下拉列表将被绑定.

I can create a component and have it's HTML as drop down and call the selector of the component in all my parent component. But, what I want is I need to pass key to this common control and this key will be sent to service and service will give only matching record and as per these records Dropdown will get bind.

这是我的伪代码:

<div class="form-group">
            <label class="col-md-2 control-label">Forms</label>
            <div class="col-md-3">
              <select class="form-control">
                <option value="Expression">Expression</option>
                <option value="Tender">Tender</option>
                <option value="Other">Other</option>
              </select>
            </div>
          </div>

相反,我想要这样的东西:

Instead of this i want something like this:

 <div class="form-group">
            <label class="col-md-2 control-label">Forms</label>
            <div class="col-md-3">
             COMMONCONTROL('KEY')
            </div>
          </div>

在角度2中实现此目标的方法是什么?

What is the way to achieve this in angular 2?

谢谢

推荐答案

您应该只创建一个实现

You should just create a component which implements the ControlValueAccessor interface and then connect it with the ngModel of the select element. For better usage i would suggest to implement an abstract class first:

import { Provider, forwardRef, Type, OpaqueToken } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export abstract class AbstractValueAccessor implements ControlValueAccessor {
    private _value: any = null;
    public onChange = (_) => { };
    public onTouched = () => { };

    public get value(): any {
      return this._value;
    }

    public set value(v: any) {
      if (v !== this._value) {
        this._value = v;
        this.onChange(v);
      }
    }

    public writeValue(value: any) {
      this._value = value;
      this.onChange(value);
    }

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

    public registerOnTouched(fn: () => void): void {
      this.onTouched = fn;
    }
}

export function MakeProvider(type: any) {
  return {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => type),
    multi: true
  };
}

有关已实现的值访问器的外观和工作方式的更多信息,请参见此处.有关以角度显示的各种访问器实现的信息,请在此处.

More information about how an implemented value accessor looks like and works can be found here. For info about the various accessor implmentations in angular look here.

然后使用它扩展您的组件:

And then extend your component with it:

import { Component, ChangeDetectionStrategy, Input, SimpleChanges, OnChanges } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { AbstractValueAccessor, MakeProvider } from './abstract-value-accessor';

@Component({
    selector: 'custom-select',
    templateUrl: './custom-select.component.html',
    providers: [MakeProvider(CustomSelectComponent)],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomSelectComponent extends AbstractValueAccessor implements OnChanges {
    private data$$ = new BehaviorSubject<any[]>([]);

    @Input()
    public dataKey: string;

    public data$ = this.data$$.asObservable();

    public get hasData$() {
        return this.data$.map(data => data.length > 0);
    }

    constructor(private dataService: MyDataService) {
        super();
    }

    ngOnChanges(changes: SimpleChanges) {
        if(changes.dataKey && changes.dataKey.currentValue) {
           this.getData(changes.dataKey.currentValue);
        }
    }

    private getData(dataKey: string) {
        this.dataService.get(dataKey).take(1).subscribe(data => this.data$$.next(data));
    }
}

然后在组件的模板中将其绑定到select:

And in your component's template you bind it to the select:

<select [(ngModel)]="value" *ngIf="hasData$ | async">
    <option [value]="option.value" *ngFor="let option of data$ | async">{{ option.name }}</option>
</select>

然后,您可以在任何需要的地方使用它:

Then you can use it where ever you want like:

<custom-select dataKey="test"></custom-select>

注意:此代码未经测试,仅提供正确方向的方法.

Note: This code is untested and only offers a way in the right direction.

这篇关于如何在Angular 2/4中创建通用控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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