I have a FormGroup for credit card inputs. And for formatting inputs, I have a directive with selector 'appCreditCardFormat'. Simplified version is below:
<input
formControlName="cardNo"
appCreditCardFormat
>
appCreditCardFormat listens events as shown below and formats input:
@HostListener('input', ['$event.target.value'])
onChangeInput = (creditCardNo: string) => {...}
I save the state of this input. Whenever user comes to the page of this input I use patchValue() function of FormGroup to set previously entered value. On the component, I check if previous value is present, then patchvalue:
const componentState = this.mediator.stateSnapshots.getState(this._componentState);
if (componentState) {
formGroup.patchValue(componentState!.getFormSnapshot(), { emitEvent: true });
}
But the problem starts here. Even though I see correct value, I don't see it in correct format. For example, I need to see in this format "4123 4245..." but instead I see this value onscreen "41234245...". Because the HostListener on appCreditCardFormat doesn't catch input event. If I change value after patchValue() input event triggers, and I see the input with correct format again.
I don't know much about but it seems like an Angular bug. I would be happy with any suggesstions.
example: playground link
CodePudding user response:
Your issue is that your host listener listens to the input change value, not the actual control value accessor itself.
Here is a demo example, working
You have to understand that the HTML Input element is NOT a form control : the form control is an Angular concept, that too listens to the input.
This means that when you update the value on the input by hand, it works, but when you do it from the form control, the input is not changed.
Also, you will see that if you put back the code in the ngOnInit of the app component, it will still not work : that's because the directive is created AFTER its parent. I would suggest you implement a REAL control value accessor on this component.