问题
I want to create a custom InputCustom
component and use it to create model-driven forms.
My custom component just wraps an input field and uses Bootstrap material design
for look'n'feel.
@Component({
selector:'inputCustom',
template:`
<div class="form-group label-floating is-empty">
<label class="control-label" for="input">Type here</label>
<input class="form-control" id="input" type="text">
<p class="help-block">Some help text</p>
<span class="material-input"></span>
</div>
`})
class InputCustom{....}
In Angular2 when you create a model-driven form
<form [ngFormModel]="formRef">
<input type ="email" ngControl="email">
</form>
all Controls
present on form elements are registered into a ControlGroup
. By using the formRef you can track field values inside controllers.
@Component({...})
class FormController{
formRef: ControlGroup;
constructor(...){
this.form.valueChanges.subscribe(data => console.log('changes', data));
}
}
Now, I want people to use my component like this
<form [ngFormModel]="formRef">
<inputCustom type ="email" ngControl="email">
</form>
Q1: Do I need write my own custom ngControl
directive?
Q2: How to propagate ngControl
to the inner <input>
element wrapped by <inputCustom>
?
Q3: How should I register my Control
inside the surrounding forms ControlGroup
?
回答1:
I see two ways to implement that:
Provide your control as parameter of your custom component:
@Component({ selector: 'inputCustom', template: ` <input [ngFormControl]="control"/> ` export class FormFieldComponent { (...) @Input() control: Control; }
This way your input will automatically takes part of the form defined in the parent component.
Implement an ngModel-compliant component. It's a bit longer to implement (you need to implement and register a
ControlValueAccessor
within a custom directive) but this way you will be able to use directly thengFormControl
andngModel
directly on your custom component.<inputCustom type ="email" [ngFormControl]="email">
See this question for more details: Angular 2 custom form input
I think that this article could interest you:
- Implementing Angular2 forms – Beyond basics (part 2) - http://restlet.com/blog/2016/02/17/implementing-angular2-forms-beyond-basics-part-2/
回答2:
I guess a custom ValueAccessor should do.
See
- https://plnkr.co/edit/Bz7wLC5qq7s6Fph1UwpC?p=preview (value accessor provided by DI)
providers: [provide(NG_VALUE_ACCESSOR, {useClass: UIDropdownComp, multi: true})]
})
export class UIDropdownComp implements ControlValueAccessor {
- http://plnkr.co/edit/slVMz6Kgv6KlnUNMDe3o?p=preview (ngControl injected into the component and value accessor assigned "manually"
export class Address implements ControlValueAccessor{
addressForm: ControlGroup;
value:any;
addressForm: ControlGroup;
constructor(@Optional() ngControl: NgControl, elementRef: ElementRef,fb: FormBuilder) {
ngControl.valueAccessor = this;
See also https://github.com/angular/angular/issues/2543
回答3:
Angular 2 material which implements custom input form element is a great source of information to see how to implement ValueAccessor.
So just dive in the source code here and have a look at the input component : https://github.com/angular/material2
来源:https://stackoverflow.com/questions/35647431/applying-angular2-form-directives-to-custom-input-form-elements