angulartypescriptangular-reactive-forms

What is the way to pass pre-populated values to Angular 2 reactive form input


import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

import { User } from '../account.interface';
import { AF } from '../angularfire.service';

@Component({
  selector: 'app-account',
  templateUrl: './account.component.html',
  styleUrls: ['./account.component.less']
})
export class AccountComponent implements OnInit {
  public error: any;
  user: FormGroup;
  onSubmit() {
    console.log(this.user.value, this.user.valid);
  }

  currentUserDetails = [];
  firstName: string = '';
  lastName: string = '';
  email: string = '';
  phone: string = '';
  bio: string = '';
  userID: string = '';

  constructor(private afService: AF) {
    // Get current user details and push to array.  This is due to input values overwriting ngModels.
    afService.getCurrentUserInfo().then(currentUserDetails => {
      let currentUser = [];
      currentUser.push(currentUserDetails);
      this.firstName = currentUser[0].firstName;
      this.lastName = currentUser[0].lastName;
      this.email = currentUser[0].email;
      this.phone = currentUser[0].phone;
      this.bio = currentUser[0].bio;
      this.userID = currentUser[0].userID;
    }).then(() => {

    })
  }

  // Update the user details with the form entry.
  // updateUserEntry(firstName, lastName, phone, bio) {
  //   this.afService.updateUserEntry(this.userID, firstName, lastName, phone, bio).then(() => {
  //     location.reload();
  //   }).catch((error) => {
  //     this.error = error;
  //     console.log("error");
  //   });
  // }

  ngOnInit() {
    this.user = new FormGroup({
      fname: new FormControl(this.firstName, [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
      lname: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
      phone: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
      bio: new FormControl('', [Validators.required, Validators.minLength(5), Validators.maxLength(50)]),
    });
  }

}

I know, it's probably a really simple fix, but I'm just not seeing it. I have my reactive formControl in my ngOnInit, but I need to pass the preset values into each input (which is this.firstName, this.lastName, etc.). When the view loads, the inputs are empty.

I believe the values aren't showing up because the form is loading before the values are populated. Any ideas on how to fix this?


Solution

  • You would be right. ngOnInit is already done before your getCurrentUserInfo is finished receiving data from your service. It is working asynchronously to avoid slowing down the application.

    You either need to apply an observable to watch when your asynchronous request is done and the data is loaded or you can simply set your user new FormGroup inside of the "then" like this:

    afService.getCurrentUserInfo().then(currentUserDetails => {
        let currentUser = [];
        currentUser.push(currentUserDetails);
        this.firstName = currentUser[0].firstName;
        this.lastName = currentUser[0].lastName;
        this.email = currentUser[0].email;
        this.phone = currentUser[0].phone;
        this.bio = currentUser[0].bio;
        this.userID = currentUser[0].userID;
    
        this.user = new FormGroup({
          fname: new FormControl(this.firstName, [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
          lname: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
          phone: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
          bio: new FormControl('', [Validators.required, Validators.minLength(5), Validators.maxLength(50)]),
        });
    })
    

    Better yet, you can create a new method for reusability:

    SetFormGroup() {
        this.user = new FormGroup({
          fname: new FormControl(this.firstName, [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
          lname: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
          phone: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]),
          bio: new FormControl('', [Validators.required, Validators.minLength(5), Validators.maxLength(50)]),
        });
    }
    

    And call that method inside the "then".