Compiler v2
Compiler v2

Reputation: 3605

Cannot assign variables to values of input in Angular 9

Problem Statement

I cannot seem to assign my variable values into my HTML input values, and there is an error in the console that says: TypeError: Cannot read property 'firstName' of undefined. Even though the error does not affect my app's function.


What I am trying to do

I am trying to make an edit page for the user where they can update the fields as they like. I get data from my service and display the person in the inputs in the HTML. This would allow the user to edit the current info and not have to retype it again.


Code

Component

export class EditDocumentComponent implements OnInit {

  // Is for population the fields in the UI so the user does not have to type in everything again
  private savedDocument: Will;

  // The current person ID that has been selected
  private personId: number;

  private form: FormGroup;

  constructor(private builder: FormBuilder, private serv: DataService, private route: ActivatedRoute) {
        this.route.queryParams.subscribe(params => {
          this.personId = params["personId"];
        });
   }

  ngOnInit() {
    // Calls service which gets a single person from the backend server
    this.serv.getSinglePersonById(this.personId).subscribe((result: Will) => {
      this.savedDocument = result;
    });

    this.form = this.builder.group({
      firstName: [''],
      lastName: [''],
      dateOfBirth: [''],
      postalAddress: [''],
      city: [''],
      country: [''],
      provinceState: [''],
    });
  }

  private sendUpdatedData() {
    console.log("Hit submit button");
    console.log("Person: " + this.savedDocument.postalAddress);
  }
}

Explanation of Code

As you can see, I have a personID where it goes to the service and gets sent to the backend where it gets a single person. After that, the returning data gets assigned to savedDocument and that is the variable I use to display the data in the UI. Since I am getting firstName is undefined, but I made sure it is not by placing a console.log() in the method that submits the form which is called: sendUpdatedData(). It is not undefined.

HTML

<body>
  <h1 class="title">Edit your document here</h1>

  <form [formGroup]="form">

    <!-- Section 1 -->
    <section class="form1">
      <mat-form-field appearance="outline" class="firstName">
        <mat-label>First Name</mat-label>
        <input matInput type="text" maxlength="50" value="{{savedDocument.firstName}}" formControlName="firstName">
      </mat-form-field><br>

      <!-- When I do this, it displays the data, which means it is not undefined
      <h1>{{savedDocument.firstName}}</h1>

      <mat-form-field appearance="outline" class="lastName">
        <mat-label>Last Name</mat-label>
        <input matInput type="text" maxlength="50" value="{{savedDocument.lastName}}" formControlName="lastName">
      </mat-form-field><br>

      <mat-form-field appearance="outline" class="dob">
        <mat-label>Date of Birth</mat-label>
        <input matInput type="text" maxlength="50" value="{{savedDocument.dateOfBirth}}" formControlName="dateOfBirth">
      </mat-form-field>
    </section>

... <!-- More here -->

</form>
</body>

Explanation of Code

I am using value="{{savedDocument.field}}" in the input, but it does not show the data.

Also, when I remove the [formGroup] from the <form> tag, it does display the data in the value.

Does not display data in the value of input tags

<form [formGroup]="form">
...
</form>

Displays data in the value of input tags

<form>
...
</form>

Upvotes: 0

Views: 1652

Answers (1)

NathanH
NathanH

Reputation: 56

There are a couple of things you can do here:

1 - Use the "elvis" operator in your value statements:

{{startDocument?.firstName}}

This checks for the existence of startDocument before trying to get firstName. You would have to do this for all of your input values. You probably would want to remove the formGroup and formcontrolnames as well. You aren't really using reactive forms at that point. I don't know if you would get the values back in startDocument if you do that, though. Not really very angular, though.

2 - Use reactive forms fully. You would need to remove the value attribute from the input tags, using [formcontrolname] exclusively. Your component code would need to change to

  ngOnInit() {
    this.form = this.builder.group({
      firstName: [''],
      lastName: [''],
      dateOfBirth: [''],
      postalAddress: [''],
      city: [''],
      country: [''],
      provinceState: [''],
    });

    // Calls service which gets a single person from the backend server
    this.serv.getSinglePersonById(this.personId).subscribe((result: Will) => {
      this.form.get('firstName').setValue(result.firstName);
      this.form.get('lastName').setValue(result.lastName);
      // the rest of the form values filled out
    });


  }

Upvotes: 1

Related Questions