由于我使用了大量相同指令和.css类的输入,我想将重复的代码提取到某个组件,如下所示:
@Component({
selector: "app-input",
template: `
<div class="...">
<input type="..." name="..." class="..." [(ngModel)]="value" someDirectives...>
<label for="...">...</label>
</div>
`,
...
})
export class InputComponent implements OnInit {
// some implementation connecting external ngModel with internal "value" one
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是以这样的方式创建一个组件,它可以与ngModel一起用作普通输入:
<app-input [(ngModel)]="externalValue" ... ></app-input>
Run Code Online (Sandbox Code Playgroud)
我在互联网上找到了几个可以部分或完全过时的解决方案,如: Angular 2自定义表单输入 这可以在角度6中以更好的方式完成吗?
and*_*eas 57
我前段时间遇到了同样的问题,想要分享一个与Angular 2+一起使用的最小例子.
假设您想在应用中的任何位置使用以下代码:
<app-input-slider [(ngModel)]="inputSliderValue"></app-input-slider>
Run Code Online (Sandbox Code Playgroud)
1)现在创建一个名为的组件InputSlider.
2)在input-slider.component.html,添加以下内容:
<input type="range" [(ngModel)]="value" (ngModelChange)="updateChanges()">
Run Code Online (Sandbox Code Playgroud)
3)现在我们必须在input-slider.component.ts文件中做一些工作:
import {Component, forwardRef, OnInit} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";
@Component({
selector: "app-input-slider",
templateUrl: "./input-slider.component.html",
styleUrls: ["./input-slider.component.scss"],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputSliderComponent),
multi: true
}]
})
export class InputSliderComponent implements ControlValueAccessor {
/**
* Holds the current value of the slider
*/
value: number = 0;
/**
* Invoked when the model has been changed
*/
onChange: (_: any) => void = (_: any) => {};
/**
* Invoked when the model has been touched
*/
onTouched: () => void = () => {};
constructor() {}
/**
* Method that is invoked on an update of a model.
*/
updateChanges() {
this.onChange(this.value);
}
///////////////
// OVERRIDES //
///////////////
/**
* Writes a new item to the element.
* @param value the value
*/
writeValue(value: number): void {
this.value = value;
this.updateChanges();
}
/**
* Registers a callback function that should be called when the control's value changes in the UI.
* @param fn
*/
registerOnChange(fn: any): void {
this.onChange = fn;
}
/**
* Registers a callback function that should be called when the control receives a blur event.
* @param fn
*/
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
}
Run Code Online (Sandbox Code Playgroud)
当然,您可以使用此类添加更多功能和值检查,但我希望它能为您提供一些想法.
快速解释:
诀窍是添加提供程序NG_VALUE_ACCESSOR on the decorator of the class and implementControlValueAccessor`.
然后我们需要定义函数writeValue,registerOnChange和registerOnTouched.后两者直接调用组件的创建.这就是为什么我们需要变量(例如onChange和onTouched- 但你可以根据自己的喜好命名它们.
最后,我们需要定义一个函数,让组件知道更新底层的ngModel.我用这个功能做到了updateChanges.每当值发生变化时,都需要调用它,无论是从外部(这就是调用它的原因writeValue),还是从内部(这就是从html调用它的原因ngModelChange).
ome*_*mer 23
这也可以这样做,当你创建一个双向绑定[()]时,你可以使用相同的名称+'change'(在我们的例子中是inputModel和inputModelChange)将它绑定到一个函数,这样ngModel会在你更新时更新触发inputModelChange.emit('updatedValue').并且您只需要在组件内声明一次.
import { Component, OnInit, Output, Input, EventEmitter } from '@angular/core';
@Component({
selector: 'app-input',
template: ` <input type="text" [(ngModel)]="inputModel" (ngModelChange)="inputModelChange.emit(inputModel)"/>`,
styleUrls: ['./app-input.component.scss']
})
export class AppInputComponent {
@Input() inputModel: string;
@Output() inputModelChange = new EventEmitter<string>();
}
Run Code Online (Sandbox Code Playgroud)
Ped*_*ani 12
如果您不关心[ngModel]以模板模型或[formControl]反应形式绑定变量,则可以使用omer answer。
除此以外:
将NG_VALUE_ACCESSOR注入令牌添加到您的组件定义中:
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
...,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AppInputComponent),
multi: true
}
]
})
Run Code Online (Sandbox Code Playgroud)实施ControlValueAccessor接口:
export class AppInputComponent implements ControlValueAccessor {
writeValue(obj: any): void {
// Step 3
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
}
onChange: any = () => { };
onTouched: any = () => { };
}
Run Code Online (Sandbox Code Playgroud)管理value何时更改:
private _value;
public get value(){
return this._value;
}
public set value(v){
this._value = v;
this.onChange(this._value);
this.onTouched();
}
writeValue(obj: any): void {
this._value = obj;
}
// Optional
onSomeEventOccured(newValue){
this.value = newValue;
}
Run Code Online (Sandbox Code Playgroud)现在您可以使用 <app-input [(ngModel)]="externalValue" ... ></app-input>
| 归档时间: |
|
| 查看次数: |
20688 次 |
| 最近记录: |