In my Spring + Angular + MYSQL project I have to manage three lists, where the third depends on the second, and the second on the choices the user takes in the first. I'm trying to connect the first and second list, but it gives me the following error:
ERROR TypeError: Cannot read property 'id' of undefined at tipo-struttura.component.ts:36
i have create the DB query with the link between the two lists:
CREATE TABLE `struttura` (
`id` bigint(20) NOT NULL,
`struttura` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `struttura` (`id`, `struttura`) VALUES
(1, 'Strutture di elevazione verticale'),
(2, 'Strutture di elevazione orizzontale'),
(3, 'Strutture di elevazione inclinate'),
(4, 'Strutture di elevazione spaziali'),
(5, 'Aperture');
CREATE TABLE `struttura_due` (
`id` bigint(20) NOT NULL,
`struttura_due` varchar(255) DEFAULT NULL,
`struttura_id_id` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `struttura_due` (`id`, `struttura_due`, `struttura_id_id`) VALUES
(1, 'Strutture a pareti portanti in muratura', 1),
(2, 'Strutture per impalcati piani', 2),
(3, 'Strutture per coperture piane', 2),
(4, 'Strutture per coperture inclinate', 3),
(5, 'Strutture voltate', 4);
ALTER TABLE `struttura`
ADD PRIMARY KEY (`id`);
ALTER TABLE `struttura_due`
ADD PRIMARY KEY (`id`),
ADD KEY `FK9eqhylq6sc1yseu3cglwffnsy` (`struttura_id_id`);
ALTER TABLE `struttura`
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
ALTER TABLE `struttura_due`
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
ALTER TABLE `struttura_due`
ADD CONSTRAINT `FK9eqhylq6sc1yseu3cglwffnsy` FOREIGN KEY (`struttura_id_id`) REFERENCES `struttura` (`id`);
COMMIT;
FRONT-END struttura.ts
export class Struttura {
id: number
struttura: string
}
struttura-due.ts
import { Struttura } from "./struttura"
export class StrutturaDue {
id: number
struttura_due: string
struttura_id_id: Struttura
}
elementi-struttura.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Struttura } from '../classes/strutture/struttura';
import { StrutturaDue } from '../classes/strutture/struttura-due';
@Injectable({
providedIn: 'root'
})
export class ElementiStrutturaService {
url: string
constructor(private http: HttpClient) {
this.url = 'http://localhost:8080/';
}
public getStruttura():Observable<Struttura[]> {
return this.http.get<Struttura[]>(this.url + "struttura");
}
public getStrutturaDue():Observable<StrutturaDue[]> {
return this.http.get<StrutturaDue[]>(this.url + "strutturaDue");
}
}
tipo-struttura.component.ts (error on line 36 -> if (t.struttura_id_id.id === this.strutt[index].id) {
import { Component, OnInit } from '@angular/core';
import { Struttura } from '../classi-servizi/classes/strutture/struttura'
import { StrutturaDue } from '../classi-servizi/classes/strutture/struttura-due'
import { ElementiStrutturaService } from '../classi-servizi/service/elementi-struttura.service';
@Component({
selector: 'app-tipo-struttura',
templateUrl: './tipo-struttura.component.html',
styleUrls: ['./tipo-struttura.component.css']
})
export class TipoStrutturaComponent implements OnInit {
strutt: Struttura[];
strutt2: StrutturaDue[];
selectedElement = [];
selectedIndex: number;
constructor(
private service: ElementiStrutturaService
) { }
ngOnInit() {
this.service.getStruttura().subscribe(data => {
this.strutt = data;
console.log(this.strutt)
})
this.service.getStrutturaDue().subscribe(data => {
this.strutt2 = data;
console.log(this.strutt2)
})
}
onChange(index: number) {
this.selectedElement = []
this.strutt2.forEach(t => {
if (t.struttura_id_id.id === this.strutt[index].id) {
this.selectedElement.push(t)
}
})
this.selectedIndex = 0;
}
}
tipo-struttura.component.html
<div class="container">
<div class="titolo" style="text-align: center;margin-top: 30px; font-size: 30px;">
<p><b>INDIVIDUAZIONE DELLE STRUTTURE</b></p>
</div>
<div class="card my-5">
<div class="card-body">
<form>
<div class="form-group">
<label for="struttura">
<p><b>Struttura</b></p>
</label>
<select value="structure" class="form-control" id="structure" (change)="onChange($event.target.value)" name="struttura">
<option selected disabled>
Seleziona
</option>
<option [value]="i" *ngFor="let array of strutt; index as i">
{{ array.struttura }}
</option>
</select>
<label></label>
<p><b>Struttura Due</b></p>
<select [(ngModel)]="selectedIndex" style="margin-top: 30px;" value="struttura" valure="struttura" class="form-control" id="structure" name="struttura">
<option selected disabled>
Seleziona
</option>
<option [value]="i" *ngFor="let arrays of selectedElement; index as i;">
{{ arrays.strutturaDue }}
</option>
</select>
A good way to deal with that, is before checking if the id's are the same, you check if the object exists.
if (t.struttura_id_id !== undefined) {
if (t.struttura_id_id.id === this.strutt[index].id) {
this.selectedElement.push(t)
}
};
It's probably happening because you have some data broken in your database.
Changing the subject:
It's a good practice to use Template Strings when you're concatenating data. So, you can use it on your service.
Instead of:
public getStruttura():Observable<Struttura[]> {
return this.http.get<Struttura[]>(this.url + "struttura");
}
Use:
public getStruttura():Observable<Struttura[]> {
return this.http.get<Struttura[]>(`${this.url}${struttura}`);
}