Home > Mobile >  Angular - ERROR TypeError: Cannot read properties of undefined (reading 'vehicle_image')
Angular - ERROR TypeError: Cannot read properties of undefined (reading 'vehicle_image')

Time:09-22

In my Angular-12 project I am trying to edit data that has image. The code is shown below:

interface:

export class VehicleResponse {
  results!: { vehicle: IVehicle };
}

export interface IVehicle {
  id?: number;
  registration_number: string;
  vehicle_image?: any;

}

service:

    getVehicleById(id: number): Observable<VehicleResponse> {
      return this.http.get<VehicleResponse>(this.api.baseURL   'vehicles/fetchbyid/'   id, this.httpOptions);
    }

    public updateVehicle(id: number, data: any) {
      return this.http.post(this.api.baseURL   'vehicles/update/'   id, data, this.httpOptions1);
    }

component

import {
  IVehicle,
  VehicleResponse
} from 'src/app/models/vehicle.model';
import {
  VehicleService
} from 'src/app/services/vehicle.service';

editForm!: FormGroup;
vehicle!: IVehicle;
vehicledata!: IVehicle;
isLoading = false;
data: any;
isSubmitted = false;
_id!: number;
vehicleImageDirectoryPath: any = this.api.imageURL   'vehicle_images/';
url = '';
files ? : any;

constructor(
  private fb: FormBuilder,
  private router: Router,
  private api: ApiService,
  private route: ActivatedRoute,
  private store: Store < AppState > ,
  private vehicleService: VehicleService
) {}

onSelectFile(event: any) {
  if (event.target.files && event.target.files[0]) {
    var reader = new FileReader();

    reader.readAsDataURL(event.target.files[0]); // read file as data url
    this.files = event.target.files[0]; // associates the file to the a different property
    reader.onload = (event: any) => { // called once readAsDataURL is completed
      //   console.log(event);
      this.url = event.target.result;
    }
  }
}

editVehicle() {
  this.editForm = this.fb.group({
    registration_number: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(50)]],
    vehicle_image: ['', [
      RxwebValidators.extension({
        extensions: ["jpg", "jpeg", "bmp", "png", "gif", "svg"]
      })
    ]]
  });
}

loadVehicleById() {
  this.vehicleService.getVehicleById(this._id)
    .subscribe(
      (data: VehicleResponse) => {
        this.vehicledata = data.results.vehicle;
        this.editForm.patchValue({
          registration_number: this.vehicledata.registration_number,
          vehicle_image: this.vehicledata.vehicle_image,
        });
        this.isLoading = false;
      }
    );
}

ngOnInit(): void {
  this._id = this.route.snapshot.params['id'];
  bsCustomFileInput.init();
  this.editVehicle();
  this.loadVehicleById();
  this.isLoading = false;
}

submitForm() {
  this.isSubmitted = true;
  // stop here if form is invalid
  if (this.editForm.invalid) {
    return;
  }
  this.isLoading = true;

  const formVehicleData = this.editForm.getRawValue();
  const formData = new FormData();

  formData.append('registration_number', formVehicleData.registration_number);
  if (this.files) {
    formData.append("vehicle_image", this.files, this.files.name);
  }
  this.vehicleService.updateVehicle(this._id, formData).subscribe(res => {
    this.data = res;
  });
}
<div class="card-body">
  <form [formGroup]="editForm" (ngSubmit)="submitForm()">

    <div class="col-lg-4">
      <div class="form-group">
        <label for="registration_number">Registration No.:<span style="color:red;">*</span></label>
        <input type="text" formControlName="registration_number" placeholder="XB-547-AG" class="form-control" required/>
      </div>
      <div *ngIf="isSubmitted || (fc.registration_number.touched && fc.registration_number.invalid)">
        <div *ngIf="fc.registration_number.hasError('required')">
          <div class="text-danger">
            Registration Number is required!
          </div>
        </div>
        <div *ngIf="fc.registration_number.hasError('minlength')">
          <div class="text-danger">
            Registration Number cannot be less than 2 characters!
          </div>
        </div>
        <div *ngIf="fc.registration_number.hasError('maxlength')">
          <div class="text-danger">
            Registration Number cannot be more than 50 characters!
          </div>
        </div>
      </div>
    </div>

    <div class="col-lg-4">
      <div class="form-group">
        <label for="vehicle_image">Vehicle Image:</label>
        <div class="card-body box-profile">
          <div class="text-center">
            <img class="profile-user-img img-fluid img-circle" [src]="vehicledata.vehicle_image ? vehicleImageDirectoryPath vehicledata.vehicle_image : url || 'assets/img/no-image.png'" alt="No Vehicle Image" onerror="this.src='assets/img/no-image.png'" style="height:150px; width:150px">
          </div>
          <div class="form-group">
            <input formControlName="vehicle_image" id="vehicle_image" type="file" class="form-control" accept=".jpg,.jpeg,.bmp,.png,.gif,.svg" (change)="onSelectFile($event)">
            <div *ngIf="fc.vehicle_image.touched && fc.vehicle_image.invalid">
              <div *ngIf="fc.vehicle_image.hasError('extension')">
                <div class="text-danger">
                  Enter valid File Type!
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="card-footer">
      <button type="submit" class="btn btn-success" [disabled]="isLoading" class="btn btn-success" (click)="editValidate()">
                  <span *ngIf="isLoading" class="spinner-border spinner-border-sm mr-1"></span>
                  <i class="fa fa-save" aria-hidden="true"></i> Save</button>
    </div>
  </form>
</div>

While trying to retrieve and view the data before I eventually update, I got this error:

ERROR TypeError: Cannot read properties of undefined (reading 'vehicle_image') at VehicleEditComponent_Template (vehicle-edit.component.html:245)

It highlights this page:

[src]="vehicledata.vehicle_image ? vehicleImageDirectoryPath vehicledata.vehicle_image : urlVehicle || 'assets/img/no-image.png'"

But the registration_number was displayed. vehicle_image exists. Could it be because the image is null?

How do I resolve this?

Thanks

CodePudding user response:

I think the issue here is with vehicledata, it is undefined and you are unable to read any property on it.

You can use optional chaining operator in the html which I have added in the below code:

<div class="text-center">
            <img class="profile-user-img img-fluid img-circle" [src]="vehicledata?.vehicle_image ? vehicleImageDirectoryPath vehicledata.vehicle_image : url || 'assets/img/no-image.png'" alt="No Vehicle Image" one rror="this.src='assets/img/no-image.png'" style="height:150px; width:150px">
          </div>

Another way could be to add the *ngIf directive to only show the image tag if vehicledata is available. I'm not sure this will work for you as I can see you have already added no-image url.

CodePudding user response:

Your vehicledata is initialized only inside loadVehicleById method, but template is used without any *ngif annotation to prevent variable use before it initialized.

You can at least extend your SRC interpolation expression to include null check:

[src]="(vehicledata && vehicledata.vehicle_image) ? vehicleImageDirectoryPath vehicledata.vehicle_image : url || 'assets/img/no-image.png'" alt="No Vehicle Image" one rror="this.src='assets/img/no-image.png'"
  • Related