I am using a template for a text inputs and feedback messages to simplify my html code. This passes in variable string called label
and populates the placeholder value for this input, and also uses the same string for the invalid-feedback
message, but for the latter I want the correct a or an depending on if the label
starts with a vowel or not. I currently use the registerOnTouched()
function in text-input-component.ts
as this is being called when the inputs are clicked/typed into to correct the feedback messages but I feel like there is a better solution/place to do this check.
Maybe something like a ternary operator or a pipe in the template?
And theoretically I could omit all the vowels except E from my check but that isn't future proof.
Form:
<app-text-input [formControl]="$any(loginForm.controls['email'])" [label]="'Email'" [type]="'email'"></app-text-input>
<app-text-input [formControl]="$any(loginForm.controls['password'])" [label]="'Password'" [type]="'password'"></app-text-input>
Text-Input Template CSS:
<div class="form-group">
<input
[class.is-invalid]="control.touched && control.invalid"
type={{type}}
class="form-control"
[formControl]="control"
placeholder={{label}}
>
<div *ngIf="control.errors?.['required']" class="invalid-feedback">Please enter a{{labelAfterVowelCheck}}</div>
</div>
Text-Input Template TypeScript:
import { Component, Input, Self } from '@angular/core';
import { ControlValueAccessor, FormControl, NgControl, PatternValidator } from '@angular/forms';
@Component({
selector: 'app-text-input',
templateUrl: './text-input.component.html',
styleUrls: ['./text-input.component.css']
})
export class TextInputComponent implements ControlValueAccessor {
@Input() label?: string;
labelAfterVowelCheck = '';
@Input() type: string = 'text';
constructor(@Self() public ngControl: NgControl) {
this.ngControl.valueAccessor = this; }
writeValue(obj: any): void {
}
registerOnChange(fn: any): void {
}
registerOnTouched(fn: any): void {
this.labelAfterVowelCheck = this.label!;
if(["A","E","I","O","U","a","e","i","o","u"].some(vowel => this.label?.startsWith(vowel))){
this.labelAfterVowelCheck = 'n ' + this.label;
}
else{
this.labelAfterVowelCheck = ' ' + this.label;
}
}
get control(): FormControl {
return this.ngControl.control as FormControl;
}
}
-
2\$\begingroup\$ an honorable request, an hour, a used car, a one-armed bandit. The rule you are implementing is not correct. You need to consider the phonetics, not the spelling of the input. \$\endgroup\$Flater– Flater2023年01月10日 22:48:27 +00:00Commented Jan 10, 2023 at 22:48
-
\$\begingroup\$ @Flater oof, that didn't even occur to me, realistically because I am the only one providing the input text, I could just define some constants for the ones that require the n and just take the hit when I need another one \$\endgroup\$WhatsThePoint– WhatsThePoint2023年01月11日 09:29:34 +00:00Commented Jan 11, 2023 at 9:29
1 Answer 1
Just a couple ideas:
- I might separate out the "validation" into its own function,
isValid
here, but you can create a better name. ie.
registerOnTouched(fn: any): void {
this.labelAfterVowelCheck = this.label!;
if(isValid(this.label)){
this.labelAfterVowelCheck = 'n ' + this.label;
}
else{
this.labelAfterVowelCheck = ' ' + this.label;
}
}
With this change, it's easier to see that you don't need the first assignment (as it will be redone in the line below below). And as you hint at, a ternary dries it up a little:
registerOnTouched(fn: any): void {
this.labelAfterVowelCheck = (isValid(this.label) ? 'n ' : ' ') + this.label;
}
- The validation itself can be simplified with a regular expression (although I get the sense this code is temporary). ie.
/^[aeiou]/i.exec(label)
Hope this helps!
-
\$\begingroup\$ Thanks for the prompt reply. The first assignment was actually a remnant of some previous logic that I forgot was still there. I have gone for idea 1. Would you say it could be better to create my own pipe for this or is that getting to complex for what it is? \$\endgroup\$WhatsThePoint– WhatsThePoint2023年01月10日 09:20:18 +00:00Commented Jan 10, 2023 at 9:20