Reputation: 39
I'm working in a simple CRUD app with Angular, and when I submit my form updating an element of the table, it creates another element instead of update the same. What is wrong?
Service Class:
export class EquipmentsService {
url = "https://localhost:5001/api/Equipment";
constructor(private http: HttpClient) { }
Getall(): Observable<Equipments[]>{
return this.http.get<Equipments[]>(this.url);
}
GetWithId(EquipmentsID: number): Observable<Equipments>
{
const Url = `${this.url}/${EquipmentsID}`;
return this.http.get<Equipments>(Url);
}
PostEquipment(equipment: Equipments ): Observable<any>{
return this.http.post<Equipments>(this.url, equipment, httpOptions);
}
PutEquipment(equipment: Equipments): Observable<any>{
return this.http.put<Equipments>(this.url, equipment,httpOptions);
}
DeleteEquipment(equipmentId: number): Observable<any>
{
const Url = `${this.url}/${equipmentId}`;
return this.http.delete<Number>(Url, httpOptions);
}
}
Dialog Component:
export class DialogFormUpdateComponent implements OnInit {
public titleForm!: string;
formG!: FormGroup;
equip!: Equipments;
id!: number;
constructor(public dialogRef: MatDialogRef<DialogFormUpdateComponent>, private fb: FormBuilder,
private EquipmentService: EquipmentsService) {
}
ngOnInit(): void {
console.log(this.id); // It's receiving Id value
this.EquipmentService.GetWithId(this.id).subscribe(result => {
this.titleForm = "Update Equipment";
this.formG = this.fb.group({
name: [result.name, [Validators.required]],
serialNumber: [result.serialNumber, [Validators.required]],
voltage: [result.voltage, [Validators.required]],
electricCurrent: [result.electricCurrent, [Validators.required]],
oil: [result.oil, [Validators.required]],
date: [result.date, [Validators.required]],
});
});
}
public SendFormUpdate(): void {
let newDate: moment.Moment = moment.utc(this.formG.value.date).local();
this.formG.value.date = newDate.format("YYYY-MM-DD");
const equipment: Equipments = this.formG.value;
this.EquipmentService.PutEquipment(equipment).subscribe(result => {
alert("Equipment was updated with success");
this.formG.reset();
this.dialogRef.close();
})
}
Cancel() {
this.dialogRef.close();
this.formG.reset();
}
}
Equipment Component:
export class EquipmentsComponent implements OnInit {
ELEMENT_DATA!: Equipments[];
form: any;
titleForm!: string;
displayedColumns: string[] = ['name', 'serialNumber', 'voltage', 'electricCurrent', 'oil', 'date', 'actions'];
@Output() equipID: EventEmitter<number>= new EventEmitter<number>();
public dataSource = new MatTableDataSource<Equipments>(this.ELEMENT_DATA);
constructor(private EquipmentService: EquipmentsService, public dialog: MatDialog,
public DialogUpate: MatDialog, public DialogComponentUpdate: DialogFormUpdateComponent) { }
ngOnInit(): void {
//getall on start
this.EquipmentService.Getall().subscribe(result => {
this.dataSource.data = result as Equipments[];
});
}
//Open Create Form
NewEquipemnt(): void {
const dialogRef = this.dialog.open(DialogFormComponent,{
minWidth: '300px', disableClose: true
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
//get all
this.EquipmentService.Getall().subscribe(result => {
this.dataSource.data = result as Equipments[];
});
});
}
//Open Update Form
public UpdateEquipment(EquipId: number): void
{
const dialogRef = this.DialogUpate.open(DialogFormUpdateComponent,{
minWidth: '300px', disableClose: true,
});
dialogRef.componentInstance.id = EquipId;
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
//get all
this.EquipmentService.Getall().subscribe(result => {
this.dataSource.data = result as Equipments[];
});
});
}
}
My update button get a data of element will be updated, but when I click in submit is created other element in my DB
Equipment Controller:
namespace TreeApi.Controllers
{
[ApiController]
[Route("Api/[Controller]")]
public class EquipmentController : ControllerBase
{
private readonly ContextEquipment _ContextEquipment;
public EquipmentController (ContextEquipment context)
{
_ContextEquipment = context;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Equipments>>> GetAllAsync()
{
return await _ContextEquipment.Equipment.ToListAsync();
}
[HttpGet("{EquipmentsID}")]
public async Task<ActionResult<Equipments>> GetEquipmentAsync(int EquipmentsID)
{
Equipments equipment = await _ContextEquipment.Equipment.FindAsync(EquipmentsID);
if(equipment == null)
{
return NotFound();
}
return equipment;
}
[HttpPost]
public async Task<ActionResult<Equipments>> PostEquipmentAsync(Equipments equipments)
{
await _ContextEquipment.Equipment.AddAsync(equipments);
await _ContextEquipment.SaveChangesAsync();
return Ok();
}
[HttpPut]
public async Task<ActionResult> PutEquipmentAsync(Equipments equipments)
{
_ContextEquipment.Equipment.Update(equipments);
await _ContextEquipment.SaveChangesAsync();
return Ok();
}
[HttpDelete("{EquipmentsID}")]
public async Task<ActionResult> DeleteEquipmentAsync(int EquipmentsID)
{
Equipments equipment = await _ContextEquipment.Equipment.FindAsync(EquipmentsID);
_ContextEquipment.Remove(equipment);
await _ContextEquipment.SaveChangesAsync();
return Ok();
}
}
}
Startup:
namespace TreeApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<ContextEquipment>(options => options.UseSqlServer
(Configuration.GetConnectionString("ConnectionDB")));
services.AddCors();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Upvotes: 1
Views: 77
Reputation: 51285
In your SendFormUpdate
method, you missed out to assign id
which is your primary key for the equipment
.
DialogFormUpdateComponent
public SendFormUpdate(): void {
let newDate: moment.Moment = moment.utc(this.formG.value.date).local();
this.formG.value.date = newDate.format("YYYY-MM-DD");
const equipment: Equipments = this.formG.value;
this.EquipmentService.PutEquipment(equipment).subscribe(result => {
alert("Equipment was updated with success");
this.formG.reset();
this.dialogRef.close();
})
}
According to DbContext.Update(Object)
method,
For entity types with generated keys if an entity has its primary key value set then it will be tracked in the Modified state.
If the primary key value is not set then it will be tracked in the Added state. This helps ensure new entities will be inserted, while existing entities will be updated.
An entity is considered to have its primary key value set if the primary key property is set to anything other than the CLR default for the property type.
Thus, new Equipment
record will be created instead of update the existing record.
Make sure that you need to assign id
(primary key) with value to equipment
to solve the concern above.
DialogFormUpdateComponent
public SendFormUpdate(): void {
...
const equipment: Equipments = this.formG.value;
equipment.id = this.id;
...
}
Upvotes: 2