I'm not sure how can I use a custom ponent if it's wrapper under another ponent.
Like:
ComponentA_withForm
|
--ComponentA1_withWrapperOfCustomInput
|
--ComponentA11_withCustomInput
if I have a structure like this:
ComponentA_withForm
|
--ComponentA11_withCustomInput
Everything's fine
But for my case (tons of async data) I need a wrapper... Is it possible somehow to do this?
Here is my fiddle code:
ComponentA:
import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
template: `<form [formGroup]="form"><custom-input-wrapper formControlName="someInput"></custom-input-wrapper></form> <p>value is: {{formVal | json}}</p>`
})
export class AppComponent {
form = this.fb.group({
someInput: [],
});
get formVal() {
return this.form.getRawValue();
}
constructor(private fb: FormBuilder) { }
}
ComponentA1:
import { Component } from '@angular/core';
@Component({
selector: 'custom-input-wrapper',
template: '<custom-input></custom-input>',
})
export class CustomInputWrapperComponent {
constructor() { }
}
ComponentA11:
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'custom-input',
template: `Hey there! <button (click)="inc()">Value: {{ value }}</button>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true,
}],
})
export class CustomInputComponent implements ControlValueAccessor {
private value = 0;
writeValue(value: number): void {
this.value = value;
}
registerOnChange(fn: (_: any) => void): void {
this.onChangeFn = fn;
}
registerOnTouched(fn: any): void {
}
inc() {
this.value = this.value + 1;
this.onChangeFn(this.value);
}
onChangeFn = (_: any) => { };
}
And here I have a working sample:
so: basically removing & refactoring code not to use CustomInputWrapperComponent
makes my code working. But I need this wrapper and I'm not sure how to pass formControlName
then.
I don't want a dirty solution with passing parent formGroup :)
I'm not sure how can I use a custom ponent if it's wrapper under another ponent.
Like:
ComponentA_withForm
|
--ComponentA1_withWrapperOfCustomInput
|
--ComponentA11_withCustomInput
if I have a structure like this:
ComponentA_withForm
|
--ComponentA11_withCustomInput
Everything's fine
But for my case (tons of async data) I need a wrapper... Is it possible somehow to do this?
Here is my fiddle code:
ComponentA:
import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
template: `<form [formGroup]="form"><custom-input-wrapper formControlName="someInput"></custom-input-wrapper></form> <p>value is: {{formVal | json}}</p>`
})
export class AppComponent {
form = this.fb.group({
someInput: [],
});
get formVal() {
return this.form.getRawValue();
}
constructor(private fb: FormBuilder) { }
}
ComponentA1:
import { Component } from '@angular/core';
@Component({
selector: 'custom-input-wrapper',
template: '<custom-input></custom-input>',
})
export class CustomInputWrapperComponent {
constructor() { }
}
ComponentA11:
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'custom-input',
template: `Hey there! <button (click)="inc()">Value: {{ value }}</button>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true,
}],
})
export class CustomInputComponent implements ControlValueAccessor {
private value = 0;
writeValue(value: number): void {
this.value = value;
}
registerOnChange(fn: (_: any) => void): void {
this.onChangeFn = fn;
}
registerOnTouched(fn: any): void {
}
inc() {
this.value = this.value + 1;
this.onChangeFn(this.value);
}
onChangeFn = (_: any) => { };
}
And here I have a working sample: https://stackblitz./edit/angular-qmrj3a
so: basically removing & refactoring code not to use CustomInputWrapperComponent
makes my code working. But I need this wrapper and I'm not sure how to pass formControlName
then.
I don't want a dirty solution with passing parent formGroup :)
Share Improve this question edited Jun 19, 2019 at 13:41 byCoder asked Jun 19, 2019 at 13:20 byCoderbyCoder 9,18427 gold badges120 silver badges259 bronze badges 3-
Why not implement
ControlValueAccessor
in yourCustomInputWrapperComponent
as well ? – abd995 Commented Jun 19, 2019 at 13:45 - @abd995I think it's dirty way as well :) – byCoder Commented Jun 19, 2019 at 14:00
- I think that's most cleanest solution you could possibly have. Passing in the form control or form group is I guess the dirty solution. – abd995 Commented Jun 19, 2019 at 14:02
2 Answers
Reset to default 4Since you don't want a dirty solution ;) , you could just implement ControlValueAccessor
in the CustomInputWrapperComponent
also. That way any change in the parent will be reflected in the child, any change in the child will be reflected in the parent as well with just few lines of code.
Wrapper Component
@Component({
selector: 'custom-input-wrapper',
template: '<custom-input [formControl]="value"></custom-input>',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputWrapperComponent),
multi: true,
}]
})
export class CustomInputWrapperComponent implements AfterViewInit, ControlValueAccessor {
public value = new FormControl();
constructor() { }
ngAfterViewInit() {
this.value.valueChanges.subscribe((x) => {
this.onChangeFn(x);
});
}
writeValue(value: number): void {
this.value.setValue(value);
}
registerOnChange(fn: (_: any) => void): void {
this.onChangeFn = fn;
}
registerOnTouched(fn: any): void {
}
onChangeFn = (_: any) => { };
}
Parent Template
<form [formGroup]="form"><custom-input-wrapper formControlName="someInput"></custom-input-wrapper></form> <p>value is: {{formVal | json}}</p>
I have made a stackbitz demo here - https://stackblitz./edit/angular-csaxcz
you cannot use formControlName
on custom-input-wrapper
because it doesn't implement ControlValueAccessor
. implementing ControlValueAccessor
on custom-input-wrapper
might be a solution but it seems to be overkill. Instead pass the control from formGroup to custom-input-wrapper
as an @Input()
and pass the inputed formControl to custom-input
app.ponent
@Component({
selector: 'my-app',
template: `<form [formGroup]="form"><custom-input-wrapper [formCtrl]="form.get('someInput')"></custom-input-wrapper></form> <p>value is: {{formVal | json}}</p>`
})
export class AppComponent {
form = this.fb.group({
someInput: [],
});
get formVal() {
return this.form.getRawValue();
}
constructor(private fb: FormBuilder) { }
}
custom-input-wrapper.ponent
@Component({
selector: 'custom-input-wrapper',
template: '<custom-input [formControl]="formCtrl"></custom-input>',
})
export class CustomInputWrapperComponent {
@Input() formCtrl: AbstractControl;
constructor() { }
}
here is a working demo https://stackblitz./edit/angular-3lrfqv
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744188301a4562311.html
评论列表(0条)