Reputation: 394
Long stroy short, i'm currently working on a directive that applies a function to a control value when modified. That function modifies the control value only in on the model side. That goes like this :
// import ...
// @Directive
export class ControlValuePipeDirective implements OnInit{
@Input() ngxControlValuePipe?: (value? :any) => any;
constructor(
private ngControl: NgControl
) {}
ngOnInit(): void {
if (this.ngxControlValuePipe === undefined) {
console.info("No method was provided to the ngxControlValuePipe directive. Ignoring it.")
}else{
this.ngControl.valueAccessor?.registerOnChange((value: any) => {
this.ngControl.control?.patchValue(this.ngxControlValuePipe ?
this.ngxControlValuePipe(value) : value,
{emitModelToViewChange: false})
}
)
}
}
}
The problem I have is when I add validators to a control like so :
// import ...
// @Component
export class AppComponent {
public profileForm: FormGroup;
constructor() {
const streetControl = new FormControl('', [Validators.maxLength(10)]);
// this.profileForm = ...
}
public editValueOnTheFly(value: any): any{
return value + ' this more than ten chars length string';
};
}
<!-- more html -->
<input id="street" type="text" formControlName="street" [ngxControlValuePipe]="editValueOnTheFly">
<!-- more html -->
If my streetControl control value gets modified in the view, then the models get's edited using the editValueOnTheFly
method, which adds a long string to the model value. This triggers the validation and invalidates the control as the new model value is longer than 10 characters.
Is there any way I can run the validators on the value that is shown in the view (which is not modified)?
Upvotes: 0
Views: 113
Reputation: 461
Because you want to avoid validation of the value modified by ControlValuePipeDirective, I propose you to separate your data model and form model.
ControlValuePipeDirective should not update form's model:
export class ControlValuePipeDirective implements OnInit{
...
ngOnInit(): void {
if (!this.ngxControlValuePipe) { return; }
this.ngControl.valueAccessor?.registerOnChange((value: any) => {
this.ngxControlValuePipe(value);
}
}
}
AppComponent's editValueOnTheFly will be responsible for profile model update:
interface ProfileModel {
street: string;
...
}
export class AppComponent {
public profileForm: FormGroup;
private profileModel: ProfileModel;
...
public editValueOnTheFly(value: any): any{
const updatedValue = value + ' this more than ten chars length string';
this.profileModel = { ...this.profileModel, street: updatedValue };
}
}
Also profileModel field can be replaced by Subject, to be able to subscribe to the profile model's changes.
Upvotes: 0