我已經創建了一些定製組件,其中的每一個實現ControlValueAccessor
,以便它們可以作爲FormGroup
內控制功能內註冊一個動態添加定製組件的一種形式的控制。通常,唯一要做的事情就是將formControlName
指令添加到HTML中的每個自定義組件。如何將formgroup
不過,我在運行時使用this技術附加這些部件的形式。
我的問題是,我不能註冊這些組件與包含FormGroup
因爲我不能聲明formControlName
指令(或任何指令,對於這一點)與動態添加控制。
有其他人發現瞭如何這可能是可能的嗎?目前,我正在包裝的另一個組件內的每個控制,這樣我就可以使用formControlName
指令,但是這僅僅是太醜陋和勞動密集型的。
下面是什麼,我已經作爲一個獨立的應用程序Angular2,這說明了一個組件(CustomComponent
)實現在啓動時被編程添加一個精簡的例子。爲了綁定CustomComponent
到FormGroup
,我已經創造CustomContainerComponent
我寧願避免。
import {
Component, ReflectiveInjector, ViewContainerRef, Compiler, NgModule, ModuleWithComponentFactories,
OnInit, ViewChild, forwardRef
} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {NG_VALUE_ACCESSOR, ControlValueAccessor, FormGroup, FormBuilder, ReactiveFormsModule} from '@angular/forms';
export class AbstractValueAccessor<T> implements ControlValueAccessor {
_value: T;
get value(): T {
return this._value;
};
set value(v: T) {
if (v !== this._value) {
this._value = v;
this.onChange(v);
}
}
writeValue(value: T) {
this._value = value;
this.onChange(value);
}
onChange = (_) => {};
onTouched =() => {};
registerOnChange(fn: (_: any) => void): void {
this.onChange = fn;
}
registerOnTouched(fn:() => void): void {
this.onTouched = fn;
}
}
export function MakeProvider(type: any) {
return {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => type),
multi: true
};
}
@Component({
selector: 'app-custom',
template: `<input type="text" [value]="value">`,
providers: [MakeProvider(CustomComponent)]
})
class CustomComponent extends AbstractValueAccessor<string> {
}
@Component({
selector: 'app-custom-container',
template: `<div [formGroup]="formGroup"><app-custom formControlName="comp"></app-custom></div>`
})
class CustomContainerComponent {
formGroup: FormGroup;
}
@NgModule({
imports: [BrowserModule, ReactiveFormsModule],
declarations: [CustomComponent, CustomContainerComponent]
})
class DynamicModule {
}
@Component({
selector: 'app-root',
template: `<h4>Dynamic Components</h4><br>
<form [formGroup]="formGroup">
<div #dynamicContentPlaceholder></div>
</form>`
})
export class AppComponent implements OnInit {
@ViewChild('dynamicContentPlaceholder', {read: ViewContainerRef})
public readonly vcRef: ViewContainerRef;
factory: ModuleWithComponentFactories<DynamicModule>;
formGroup: FormGroup;
constructor(private compiler: Compiler, private formBuilder: FormBuilder) {
}
ngOnInit() {
this.compiler.compileModuleAndAllComponentsAsync(DynamicModule)
.then((moduleWithComponentFactories: ModuleWithComponentFactories<DynamicModule>) => {
this.factory = moduleWithComponentFactories;
const compFactory = this.factory.componentFactories.find(x => x.selector === 'app-custom-container');
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
let cmp = this.vcRef.createComponent(compFactory, this.vcRef.length, injector, []);
(<CustomContainerComponent>cmp.instance).formGroup = this.formGroup;
});
this.formGroup = this.formBuilder.group({
'comp': ['hello world']
})
}
}
@NgModule({
imports: [BrowserModule, ReactiveFormsModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {
}
無代碼無哭...添加你在這裏嘗試 – smnbbrv
你是非常正確的。我會添加一些代碼 –
感謝您的更新。動態創建組件的最終用途是什麼?你想只有動態控件的動態表單,或者你想有一個一個地使用控件的能力嗎? – smnbbrv