Reputation: 23
I'm using Angular and Java with SpringBoot to edit a component. Backend works fine, checked it with postman. However, when trying to edit a component it throws a 400 Error.
The html of the edit page:
<div class="container" *ngIf="expLab"> <div class="row">
<form (ngSubmit)="onUpdate()" novalidate #f="ngForm" [formGroup]="form">
<div class="mb-3">
<div class="form group">
<label for="img" class="form-label">Logo</label>
<input class="form-control form-control-sm" id="img" type="text" formControlName="img" [(ngModel)]="expLab.img">
</div>
</div>
<div class="mb-3">
<div class="form group">
<label for="nombreE" class="form-label">Nombre del lugar</label>
<input class="form-control form-control-sm" id="nombreE" formControlName="nombreE" type="text" [(ngModel)]="expLab.nombreE">
</div>
</div>
<div class="mb-3">
<div class="form group">
<label for="inicio" class="form-label">Año de inicio</label>
<input class="form-control form-control-sm" id="inicio" formControlName="inicio" type="text" [(ngModel)]="expLab.inicio">
</div>
</div>
<div class="mb-3">
<div class="form group">
<label for="fin" class="form-label">Año de fin</label>
<input class="form-control form-control-sm" id="fin" formControlName="fin" type="text" [(ngModel)]="expLab.fin">
</div>
</div>
<div class="mb-3">
<div class="form group">
<label for="descripcionE" class="form-label">Descripción</label>
<textarea class="form-control" id="descripcionE" formControlName="descripcionE" rows="3" [(ngModel)]="expLab.descripcionE"></textarea>
</div>
</div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
<button type="submit" class="btn btn-primary" (click)="onEnviar($event)" >Actualizar</button>
</form> </div> </div>
And the TS file:
export class EditresumeComponent implements OnInit {
expLab : Experiencia = null;
form: FormGroup;
constructor(public router: Router, private sExperiencia: ExperienciaService, private activatedrouter: ActivatedRoute, private formBuilder: FormBuilder) {
this.form= this.formBuilder.group({
nombreE:[''],
inicio:[''],
fin:[''],
descripcionE:[''],
img:[''],
})
}
ngOnInit(): void {
const id = this.activatedrouter.snapshot.params['id'];
this.sExperiencia.detail(id).subscribe(
data =>{
this.expLab = data;
}
)
}
onUpdate(): void{
const id = this.activatedrouter.snapshot.params['id'];
this.sExperiencia.update(id, this.expLab).subscribe(
data=>{
this.router.navigateByUrl('/dashboard');
}, err =>{
this.router.navigateByUrl('/dashboard');
}
)
}
onEnviar(event: Event){
event.preventDefault;
if (this.form.valid){
alert("Todo salio bien ¡Enviar formuario!")
}else{
this.form.markAllAsTouched();
}
}
The model:
export class Experiencia {
id? : number;
nombreE : string;
descripcionE : string;
inicio : string;
fin : string;
localidad : string;
img: string;
constructor(nombreE: string, descripcionE: string, inicio:string, fin:string, localidad:string, img:string){
this.nombreE = nombreE;
this.descripcionE = descripcionE;
this.inicio = inicio;
this.fin = fin;
this.localidad = localidad;
this.img = img;
}
}
And the Service:
export class ExperienciaService {
expURL = 'http://localhost:8080/experiencialaboral/';
constructor(private httpCliente: HttpClient) { }
public lista(): Observable<Experiencia[]>{
return this.httpCliente.get<Experiencia[]>(this.expURL + 'lista');
}
public detail(id: number): Observable<Experiencia>{
return this.httpCliente.get<Experiencia>(this.expURL + `detail/${id}`);
}
public save(experiencia: Experiencia): Observable<any>{
return this.httpCliente.post<any>(this.expURL + 'nueva', experiencia);
}
public update(id: number, experiencia: Experiencia): Observable<any>{
return this.httpCliente.put<any>(this.expURL + `editar/${id}`, experiencia)
}
public delete(id: number): Observable<any>{
return this.httpCliente.delete<any>(this.expURL + `borrar/${id}`)
}
}
Any idea what's generating this?
I tried changing the Img type from "file" to type "text" but it didn't work.
Adding the backend Endpoints (the ones i'm calling):
@PutMapping ("/editar/{id}")
public Experiencia editExperiencia (@PathVariable int id,
@RequestParam("nombreE") String nuevoNombreE,
@RequestParam("descripcionE") String nuevaDescripcion,
@RequestParam("inicio") String nuevoInicio,
@RequestParam("fin") String nuevoFin,
@RequestParam("localidad") String nuevaLocalidad,
@RequestParam("img") String nuevaImagen) {
Experiencia expe = servexp.findExperiencia(id);
expe.setNombreE(nuevoNombreE);
expe.setDescripcionE(nuevaDescripcion);
expe.setInicio(nuevoInicio);
expe.setFin(nuevoFin);
expe.setLocalidad(nuevaLocalidad);
expe.setImg(nuevaImagen);
servexp.saveExperiencia(expe);
//reconoce la nueva Persona
return expe;
}
@GetMapping("/detail/{id}")
public ResponseEntity<Experiencia> getById(@PathVariable int id) {
if (!servexp.existsById(id)){
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
Experiencia expe = servexp.getOne(id).get();
return new ResponseEntity(expe, HttpStatus.OK);
}
Upvotes: 2
Views: 381
Reputation: 14031
In your Angular code you are submitting your data with this function:
public update(id: number, experiencia: Experiencia): Observable<any>{
return this.httpCliente.put<any>(this.expURL + `editar/${id}`, experiencia)
}
which means you are submitting experiencia
as the body
of the request.
However, in your Spring Controller, you have this signature for the mapped URL
@PutMapping ("/editar/{id}")
public Experiencia editExperiencia (@PathVariable int id,
@RequestParam("nombreE") String nuevoNombreE,
@RequestParam("descripcionE") String nuevaDescripcion,
@RequestParam("inicio") String nuevoInicio,
@RequestParam("fin") String nuevoFin,
@RequestParam("localidad") String nuevaLocalidad,
@RequestParam("img") String nuevaImagen) {
...
}
which basically is expecting multiple parameters (not just one payload set in the body
) - I think if you change your signature to something like this:
@PutMapping ("/editar/{id}")
public Experiencia editExperiencia (@PathVariable final int id,
@RequestBody Experiencia nuevaExperiencia {
...
}
Where you indicate in the signature to get the request body (and then get the different values from it) - you will achieve what you want.
Upvotes: 1