0

I am fairly new to Angular. The version I am using in Angular 7.

So, I have a list of cars in cars.component.ts which are being fetched from a JSON file using a service. Each car in the list has an edit and delete option and I also have a button to add a new car.

The edit option has an update option and when I press that, I get an error ERROR TypeError: Cannot set property 'name' of undefined. I am missing out something but not sure what exactly.

Below is the code.

cars.component.ts

import { Component, OnInit } from '@angular/core';
import { CarService } from '../service/car.service';
import { ICars } from '../cars';

@Component({
  selector: 'app-cars',
  templateUrl: './cars.component.html',
  styleUrls: ['./cars.component.css']
})
export class CarsComponent implements OnInit {

  public cars = [];

  registeredCars = [];
  selectedRow: number;
  public car: ICars;
  showNew: Boolean = false;
  submitType: string;
  loading: Boolean = false;

  constructor(private _carService: CarService) { }

  ngOnInit() {
    this.loading = true;
    //console.log('loading', this.loading);
    this._carService.fetchData().subscribe(data => this.cars = data);
  }

  onEdit(index: number) {
    this.selectedRow = index;
    this.car = new ICars;
    this.car = Object.assign({}, this.cars[this.selectedRow]);
    this.showNew = true;
    this.submitType = 'Update';
  }

  onDelete(index: number) {
    this.cars.splice(index, 1);
  }

  onNew() {
    this.car = new ICars;
    this.submitType = 'Save';
    this.showNew = true;
  }

  onSave(index: number) {
    this.selectedRow = index;
    if (this.submitType === 'Save' ) {
      this.cars.push(this.car);
    } else {
      console.log('this car', this.car.name);
      this.car[this.selectedRow].name = this.car.name;
      this.car[this.selectedRow].year = this.car.year;
    }
    this.showNew = false;
  }

  onCancel() {
    this.showNew = false;
  }
}

and this is partial code

<div class="carsList">
  <table *ngIf="loading" class="table table-striped">
    <thead >
      <tr>
        <th>#</th>
        <th>Name</th>
        <th>Year</th>
      </tr>
    </thead>
    <tbody >
        <tr *ngFor="let car of cars; let i = index">
            <td>{{ i+1 }}</td>
            <td>{{car.name | uppercase}}</td>
            <td>{{car.year}}</td>
            <td>
                <button type="button" class="btn btn-info" routerLink="/car-details/{{ i }}" placement="top" ngbTooltip="View details"><fa name='eye'></fa></button>
              </td>
            <td>
              <button type="button" class="btn btn-secondary" (click)="onEdit(i)" placement="top" ngbTooltip="Edit details"><fa name='edit'></fa></button>
            </td>
            <td>
              <button type="button" class="btn btn-danger" (click)="onDelete(i)" placement="top" ngbTooltip="Delete entry"><fa name='trash'></fa></button>
            </td>
        </tr>
    </tbody>
  </table>
  <div class="text-right">
      <button type="submit" class="btn btn-primary" (click)="onNew()">New</button>
  </div>
</div>
<!-- Edit/Add User  -->

<div class="regentry" *ngIf="showNew">
    <h2 class="text-center">{{ submitType === 'Save'? 'Register New Car' : 'Edit Car' }}</h2>
    <br>
    <form (ngSubmit)="onSave()">
      <div class="form-group row">
        <label for="name-input" class="col-2 col-form-label">Car Name</label>
        <div class="col-10">
          <input class="form-control" type="text" [(ngModel)]="car.name" name="name" required>
        </div>
      </div>
      <div class="form-group row">
        <label for="year-input" class="col-2 col-form-label">Year</label>
        <div class="col-10">
          <input class="form-control" type="text" [(ngModel)]="car.year" name="year" required>
        </div>
      </div>
      <button type="submit" class="btn btn-success">{{submitType}}</button>&nbsp;
      <button type="submit" class="btn btn-primary" (click)="onCancel()">Cancel</button>
    </form>
  </div>

  <div *ngIf="!loading"><img class="loading" src="../../assets/loading.gif" alt="loading" srcset=""></div>
3
  • Perhaps the error stems from not properly calling the constructor function ICars? new ICars() Commented Jan 25, 2019 at 6:27
  • @BenSteward ohkay... can you please elaborate, I am very new to angular and this interface concept. Commented Jan 25, 2019 at 6:38
  • If it’s an interface, then I’m not sure how to use the new keyword with it. You’ll have to research that question. I think my answer solves your immediate question, however. Commented Jan 25, 2019 at 6:41

1 Answer 1

1

You need to pass the index you are saving to your onSave function in your template: onSave(index)

However, it would be simpler, since you are already setting the selectedRow in the onEdit function, to simply remove the parameter from onSave altogether and then remove the line this.selectedRow = index.

Because you weren’t passing a parameter, index was undefined and then you assigned that undesirable value to this.selectedRow before using it to look up a value on this.car.

Removing the lines I mentioned should keep this.selectedRow in tact as a valid index number at the time you click to save.

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

Comments