I am not able to populate my form with data that I have received from a method called getbyId() from a service, in my console I see that errors: cannot read truckId of undefined, Every solution i have found is saying my form is rendered faster than the object that i want to get with a getById() method and the solution should be *ngIf ="truck" which should ,make the form wait , but it doesn't solve it just refuses to display the form thats all. IN stackblitz below https://stackblitz.com/edit/stackoverflow-49847806-kdjhdc?file=app%2Fservices%2Ftruck.service.ts
But In console i can see the URL and when I open it I see that it actually got the details from my back-end service
getTruckById(id: number): Observable<Truck> {
const url = `${this.baseUrl}/${id}`;
return this.http.get(url, {headers: this.headers})
.pipe(map(this.extractData),
tap(data => console.log(JSON.stringify(data))),
catchError(this.handleError));
}
This is the edit component completely
export class EditTruckComponent implements OnInit {
five : number = 5;
seven: number = 7;
@Input() truck: Truck;
truckIdTOUpdate: number;
processValidation = false;
dates: string;
statusCode: number;
requestProcessing = false;
truckForm = new FormGroup({
truckCode: new FormControl(Validators.maxLength(this.seven), Validators.minLength(this.five)),
date: new FormControl('', Validators.required ),
descriptions: new FormControl(Validators.maxLength(this.seven), Validators.minLength(this.five))
});
constructor( private route: ActivatedRoute, private truckService: TruckService, private router: Router) {
}
ngOnInit() {
this.getTruckDetail();
}
back() {
this.router.navigate(['/trucks'])
}
getTruckDetail() {
const truckId = +this.route.snapshot.paramMap.get('truckId');
this.truckService.getTruckById(truckId)
.subscribe((truck) => this.truck = truck)
console.log("this is the truck" + this.truck);
}
processForm() {
this.processValidation = true;
if (this.truckForm.invalid) {
return; //Validation failed, exit from method.
}
// if we are here then all good
this.preProcessConfigurations()
let truckCode = this.truckForm.get('truckCode').value.trim();
let date = this.truckForm.get('date').value.trim();
let description = this.truckForm.get('descriptions').value.trim();
if (this.truck.truckId == undefined) {
let truck = new Truck(null, truckCode, date , description);
this.truckService.createTruck(truck).subscribe((truck) => {
console.log(truck)
this.router.navigate(['/trucks']);
}, errorCode => this.statusCode = errorCode);
} else {
this.truck = new Truck(this.truck.truckId, truckCode, date, description);
this.truckService.updateTrucks(this.truck).subscribe((truck)=> {
console.log(truck);
this.router.navigate(['/trucks']);
}, errorCode => this.statusCode = errorCode);
}
}
//Perform preliminary processing configurations
preProcessConfigurations() {
this.statusCode = null;
this.requestProcessing = true;
}
}
class="btn btn-light"
title="Save Truck"
data-toggle="tooltip"
data-placement="bottom">
<i class="fa fa-save"></i> <span class="d-none d-sm-inline" *ngIf="truck?.truckId ==undefined">Save</span>
<span class="d-none d-sm-inline" *ngIf="truck?.truckId">Update</span>
</a></li>
</ul>
</nav>
</header>
<section id="department">
<div class="container-fluid">
<div class="row">
<div class="col">
<div class="card">
<div class="card-body">
<form [formGroup]="truckForm" (ngSubmit)="processForm()" id="editFormTruck" >
<!--truck code-->
<div class="form-group">
<label class="form-control-label"
for="truckCode"></label>
<input formControlName="truckCode"
id="truckCode"
class="form-control"
type="text"
name="truckCode"
min="2018-04-11" required
[(ngModel)]="truck?.truckCode"/> Truck Code
<div class="alert alert-danger" role="alert" *ngIf="truckForm.get('truckCode').invalid && processValidation" required="required" [ngClass] ="'error'">
you must have a minimum of 5 chars and maximum of 7
</div>
<div *ngIf="statusCode === 409" [ngClass] = "'success'" class="alert alert-danger" role="alert">
Truck with such Code already exists try another TruckCode.
</div>
</div>
<!--purchasedDate-->
<div class="form-group" >
<label class="form-control-label" *ngIf="truckForm.get('date').invalid && processValidation" [ngClass] ="'error'"
for="purchasedDate">date is required.</label>
<input formControlName="date"
id="purchasedDate"
class="form-control"
type="date"
name="purchasedDate"
[(ngModel)]="truck?.purchasedDate "
/> Purchased Date
</div>
I have posted all because the undefined value starts from my button's save and update when I remove them it goes down to truckCode is undefined
For better understanding this is my truckComponent That navigates to EditTruckComponent MY truckComponent shows a list of trucks and edit and delete functions now on my edit function in html i have a i just have a router link
<tr *ngFor="let truck of trucks | async">
<td>{{truck.truckId}}</td>
<a routerLink="/truckProfile/">
<td>{{truck.truckCode}}</td>
</a>
<td>{{truck.purchasedDate | date: 'yyyy-MM-dd'}}</td>
<td>{{truck.descriptions}}</td>
<td class="text-right">
<a class="btn-sm btn-outline-secondary"
ngbTooltip="Edit Truck"
placement="top">
<i class="fa fa-bus"></i> <span
class="d-none d-md-inline" routerLink="/editsTrucks/{{truck.truckId}}" >Edit</span></a>
<span data-toggle="modal" data-target="#deleteDialog">
<a href="#" class="btn-sm btn-outline-secondary"
ngbTooltip="delete truck"
placement="top">
<i class="fa fa-remove"></i>
<span class="d-none d-md-inline" (click)="deleteTruck(truck)">Delete</span></a>
</span>
</td>
So i just do a navigate with router link and on my editTruckCompnent im doing a getById on init
The issue was in my java controller
@GetMapping(value = "/trucks/{truckId}")
@ResponseStatus(HttpStatus.OK)
public final TruckDto getTruckId(@PathVariable(value = "truckId")
final Integer truckId) {
LOGGER.debug("test: truckId({})", truckId);
Truck truck = truckService.getTruckById(truckId);
return mappingService.map(truck, TruckDto.class);
}
when i added this annotation it worked @ResponseBody So response body tells the controller that the object returned should be serialized into JSON and passed back into the HttpResponse object. This is why i was getting a HttpResponse Failure
It's a design issue. In my opinion, the right way to do it is :
The EditTruckComponent parent
should be smart, do the http call and pass the truck to the EditTruckComponent
(you could use async so you don't have to subscribe and unsubscribe manualy)
Here is a clue of how I imagine the parent component :
<app-edit-truck [truck]="truck$ | async"></app-edit-truck>
export class EditTruckParentComponent {
truck$: Observable < Truck > ;
constructor(private truckService: TruckService) {
this.truck$ = this.truckService.getTruckById(truckId);
}
}
Make the EditTruckComponent
dumb, no service calls, and only inputs and outputs. Implement OnChanges to handle the truck input changes, and patch the form values.
The edit truck component would look like this :
export class EditTruckParent implements OnChanges {
@Input() truck: Truck;
constructor() {
}
ngOnChanges() {
this.truckForm.patchValue(truck);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With