0

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>
2
  • Which form you want to use? template driven form or reactive form? It seems you are mixing both the form types. Commented Apr 24, 2020 at 15:18
  • Angular has two different types of form: Reactive farms (aka dynamic ones), which are well... dynamically and template driven forms, which are a more "static" approach. You seem to use elements of both (formGroups are reactive, while value={{...}} is a more template driven approach) Commented Apr 24, 2020 at 15:27

1 Answer 1

1

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
    });


  }
Sign up to request clarification or add additional context in comments.

1 Comment

It worked! I used the elvis operator with {{...}} and it started displaying the values. Thank you for your quick answer and time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.