8

I am using the built-in pipe titlecase on an input field - username in a reactive form. It is working properly only when i am typing in the input field and its not working when i select from the browser suggestion for that input field, even when i focused out.

app.component.ts

ngOnInit() {
    this.signupForm = new FormGroup({
      'userData': new FormGroup({
        'username': new FormControl(null, [Validators.required, this.forbiddenNames.bind(this)]),
        'email': new FormControl('abc@test.com', [Validators.required, Validators.email], this.forbiddenEmails)
      }),
      'gender': new FormControl('male'),
      'hobbies': new FormArray([])
    });
}

app.component.html

<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
    <div formGroupName="userData">
        <div class="form-group">
           <label for="username">Username</label>
             <input
                  type="text"
                  id="username"
                  formControlName="username"
                  class="form-control"
                  [value]="signupForm.get('userData.username').value | titlecase">
                  <span *ngIf="signupForm.get('userData.username').errors['required']">
                      This field is required
                  </span>
          </div>
         ...
     </div>
     <button class="btn btn-primary" type="submit">Submit</button>
 </form>

When i am typing it is working fine

enter image description here

When i am selecting from the browser selection it is not working
Though i focused out of the input field its still in uppercase.

enter image description here Can someone help on what i am doing wrong.


@Haifeng Zhang This is the scenario i mentioned in the question, i replicated in your stackblitz demo

enter image description here

Avinash
  • 1,245
  • 11
  • 19

2 Answers2

2

2nd edit: enter image description here Check the very last action in the GIF, I type in space and ADD transforms to Add

That's how titlecase work, the definition is:

Transforms text to title case. Capitalizes the first letter of each word, and transforms the rest of the word to lower case. Words are delimited by any whitespace character, such as a space, tab, or line-feed character.

1st edit:

I use tempref and it works for me: Demo is here

enter image description here

app.component.html:

<form [formGroup]="signUpForm">
  <div formGroupName="userData">
    <label for="username">Username</label>
    <input type="text" formControlName="username" #username [value]="username.value | titlecase">
  </div>
  <pre>{{ signUpForm.value | json }}</pre>
</form>

app.component.ts:

 constructor(public fb: FormBuilder) {
    this.signUpForm = this.fb.group({
      userData: this.fb.group({
        username: '',
        email: ''
      })
    });
  }

It also works when I copy a uppercase 'ABC' into the input field

enter image description here enter image description here enter image description here

Haifeng Zhang
  • 30,077
  • 19
  • 81
  • 125
  • 1
    Thanks a lot @Haifeng Zhang for taking your time and answering, I had the issue when i was selecting the browser suggested selection which had Uppercase value. It was working fine when i was entering the input in my approach. Can you try removing the pipe, then save the form with uppercase input so that the browser will suggest next time when you type the same input. Next use the pipe and select the browser suggestion and check if thats transformed. – Avinash Aug 13 '18 at 20:23
  • @Avinash I upload a GIF picture and also a StackBlitz demo:) – Haifeng Zhang Aug 13 '18 at 20:53
  • 1
    i replicated the issue in the same stackblitz demo you posted and updated my question with the gif, please check on that. – Avinash Aug 13 '18 at 21:14
  • 1
    @Avinash I saw that and the definition of `titlecase` said that the words are delimited by space, tab or line-feed character, the way you *did will not trigger* `titlecase` that's why it didn't work in the scenario. RezaRahmati's suggestion will handle this case properly – Haifeng Zhang Aug 13 '18 at 21:26
  • 1
    That was informative @Haifeng Zhang , then in the approach i did also it should work after i select the browser suggestion and then add a space. – Avinash Aug 13 '18 at 21:37
2

I used another approach which is subscribing to valuechange

see live demo here at stackblitz

constructor(private fb: FormBuilder, private titleCasePipe: TitleCasePipe) {
  }

  ngOnInit() {
    this.signupForm = this.fb.group({
      'userData': this.fb.group({
        'username': [null, [Validators.required]],
        'email': ['abc@test.com', [Validators.required, Validators.email]]
      }),
      'gender': ['male'],
      'hobbies': this.fb.array([])
    });

    this.signupForm.controls.userData.get('username').valueChanges.subscribe((val) => {
      this.signupForm.controls.userData.patchValue(
        {
          username: this.titleCasePipe.transform(val)
        }, 
        { emitEvent: false })
    })
  }

and

<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
    <div formGroupName="userData">
        <div class="form-group">
           <label for="username">Username</label>
             <input
                  type="text"
                  id="username"
                  formControlName="username"
                  class="form-control"
                  >
                  <span *ngIf="signupForm.get('userData.username').errors && signupForm.get('userData.username').errors['required']">
                      This field is required
                  </span>
          </div>
     </div>
     <button class="btn btn-primary" type="submit">Submit</button>
 </form>

result

Reza
  • 18,865
  • 13
  • 88
  • 163
  • Thanks @RezaRahmati for the approach, i commented the place where we subscribe to valueChanges in your code and saved the form with uppercase input, next i uncommented and tried by selecting from the browser suggestion. It worked fine in your approach. But can you help on what i was doing wrong in my approach and letting me know why it wasn't working in my approach. – Avinash Aug 13 '18 at 20:31