I am currently working on implementing an editable datagrid feature. My goal is to click on the Edit button and only have the selected row become editable, instead of all rows becoming editable at once. I have created two templates: one for displaying data and one for editing:
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Number</th>
<th>Capacity</th>
<th>Action</th>
</tr>
</thead>
<tbody id="room" data-bind="template: {name: selectedTemplate, foreach: roomList}"></tbody>
</table>
@*Templates*@
<script type="text/html" id="baseTemplate">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: number"></td>
<td data-bind="text: capacity"></td>
<td>
<button type="button" data-bind="click: function() { $root.edit($data) }">Edit</button>
</td>
</tr>
</script>
<script type="text/html" id="editTemplate">
<tr>
<td data-bind="text: $root._id"></td>
<td>
<input type="text" class="form-control" data-bind="value: $root._number" />
</td>
<td>
<input type="text" class="form-control" data-bind="value: $root._capacity" />
</td>
<td>
<button type="button" data-bind="click: function() {$root.update($data)}">Update</button>
</td>
</tr>
</script>
ViewModel written in TypeScript:
import * as ko from 'knockout';
import { RoomDTO } from "./../DTO/roomDTO";
class RoomIndexVM {
roomList: KnockoutObservableArray<RoomDTO>;
selectedTemplate: KnockoutObservable<string>;
_id: KnockoutObservable<number>;
_number: KnockoutObservable<number>;
_capacity: KnockoutObservable<number>;
constructor() {
this.roomList = ko.observableArray();
this.selectedTemplate = ko.observable("baseTemplate");
this._id = ko.observable();
this._number = ko.observable();
this._capacity = ko.observable();
}
private getAllRooms() {
return new Promise<Array<RoomDTO>>((resolve) => {
$.ajax({
type: "GET",
url: `/api/room/getall?skip=${0}&take=${0}`
}).done((result: Array<RoomDTO>) => {
resolve(result);
}).fail(function (ex) {
console.log(`Error: ${ex}`);
});
});
}
private updateRoom(data: RoomDTO) {
return new Promise<number>((resolve) => {
$.ajax({
type: "POST",
contentType: "application/json",
data: JSON.stringify(data),
url: `/api/room/update`
}).done((result: number) => {
resolve(result);
}).fail(function (ex) {
console.log(`Error: ${ex}`);
});
});
}
private updateRoomList(result: Array<RoomDTO>) {
this.roomList.removeAll();
result.forEach((value, index) => {
this.roomList.push(value);
});
}
public changeTemplate(template: string) {
switch (template) {
case "base":
this.selectedTemplate("baseTemplate");
break;
case "edit":
this.selectedTemplate("editTemplate");
default:
}
}
public async edit(room: RoomDTO) {
this.changeTemplate('edit');
}
public async update(room: RoomDTO) {
alert("in edit");
this.changeTemplate("base");
console.log(await this.updateRoom(room));
this.updateRoomList(await this.getAllRooms());
}
public async initialize() {
this.updateRoomList(await this.getAllRooms());
}
}
window.onload = () => {
let roomIndexVM = new RoomIndexVM();
ko.applyBindings(roomIndexVM);
roomIndexVM.initialize();
}
Click here to view the result after switching templates.
Can anyone guide me on how to make only one row editable at a time?