在"原地网格编辑"中,"取消"失败



我关注这个博客来创建就地网格编辑。

http://blog.ryanvanderpol.com/knockout-edit-data-grid/

除了"取消"按钮仍然使用新值更新UI之外,其他一切都正常。

我该怎么解决?当用户单击"取消"时,我如何获取旧值并用原始值更新字段?

谢谢!

My Object structure is :
class Tour
{
tourSeriesName: string;
year: string;
tourSeriesDepartures: Array<{
departureGroupName: string;
departures: Array<{
tourName: string;
departureCode: string;
isActive: boolean;
tourId: number;
tourDepartureId: number;
assignedCoaches: Array<{
coachName: string;
seats: number;
seatsAvailable: number;
isExtensionCoach: boolean;
resourceInventoryId: number;
resourceScheduleId: number
}>;

}>;
}>;
So something like this:

<div id="departure-container" style="display: none;" data-bind="visible: TourSeriesDepartures().length>0">

<table class="table" >
<tr>
<th>Series Departure</th>
<th>Main Coach Seats</th>
<th>Departure</th>
</tr>
<tbody data-bind=" template:{name:templateToUse, foreach: currentPage }"></tbody>

</table>
</div>
</body>

<script id="itemsTmpl" type="text/html">
<!-- ko foreach: Departures -->
<tr>
<!-- ko if: $index() == 0 -->
<td style="vertical-align:middle" data-bind="text: $parent.DepartureGroupName,attr: { rowspan: $parent.Departures().length }"></td>
<td style="vertical-align:middle" data-bind="attr: { rowspan: $parent.Departures().length }">
<!-- ko if: $data.AssignedCoaches().length > 0 -->
<span data-bind="text: (($data.AssignedCoaches()[0].Seats) ? $data.AssignedCoaches()[0].Seats : '?')" ></span>
<!-- /ko -->
</td>
<!-- /ko -->

<td>
<span data-bind="text: TourName "></span>
<span data-bind="text: DepartureCode"></span>
</td>
<!-- ko if: $index() == 0 -->
<td class="buttons" data-bind="attr: { rowspan: $parent.Departures().length }" style="vertical-align:middle">
<span>
<button class="btn" data-bind="click: $root.edit"  title="edit"> Edit </button>
</span>
</td>
<!-- /ko -->
</tr>
<!-- /ko -->
</script>
<script id="editTmpl" type="text/html">

<!-- ko foreach: Departures -->
<tr > @*data-bind="click: $root.selectItem"*@
<!-- ko if: $index() == 0 -->
<td style="vertical-align:middle" data-bind="text: $parent.DepartureGroupName,attr: { rowspan: $parent.Departures().length }"></td>
<td style="vertical-align:middle" data-bind="attr: { rowspan: $parent.Departures().length }">
<!-- ko if: $data.AssignedCoaches().length > 0 -->
<span><input data-bind="value: (($data.AssignedCoaches()[0].Seats) ? $data.AssignedCoaches()[0].Seats : '?'), event: { blur: $root.here}" required /></span>
<!-- /ko -->
</td>
<!-- /ko -->

<td>
<span data-bind="text: TourName "></span>
<span data-bind="text: DepartureCode"></span>
</td>
<!-- ko if: $index() == 0 -->
<td class="buttons" data-bind="attr: { rowspan: $parent.Departures().length }" style="vertical-align:middle">
<span>
<button class="btn" data-bind="click: $root.save"  title="save"> Save </button>
<button class="btn" data-bind="click: $root.cancel"  title="cancel">Cancel</button>
</span>
</td>
<!-- /ko -->
</tr>
<!-- /ko -->


</script>
var viewModel = function (data) {
if (data != null) {
ko.mapping.fromJS(data, {}, self);
}
var self = this;
self.TourSeriesDepartures = ko.observableArray([]);

self.selectedItem = ko.observable("");

self.saveMe = function (d) {
var resourceScheduleId = d.AssignedCoaches()[0].ResourceScheduleId();
var seats = d.AssignedCoaches()[0].Seats();
//alert("in save" + this);
//viewModel.selectedItem(this);
$.ajax({
//url: "SaveTour",
url: "SaveTour/?seats=" + seats + "&rsID=" + resourceScheduleId,
data: ko.toJSON({ tour: ko.toJS(self.selectedItem) }),
type: "post",
contentType: "application/json",
success: function (result)
{ alert(result) }
});
}
// trying in place editing
self.selectedItemCache = ko.observable();

self.templateToUse = function (item) {
return self.selectedItem() === item.Departures()[0] ? 'editTmpl' : 'itemsTmpl';
};
self.edit = function (item) {
self.selectedItem(item);
self.selectedItemCache(ko.mapping.toJS(item));
};
self.cancel = function () {

if (self.selectedItemCache) {
var item = self.selectedItem();
//var index = self.list.indexOf(item);
//self.list.splice(index, 1, self.selectedBackup);
}
self.selectedItem(null);
};
self.save = function () {
var item = self.selectedItem();
var resourceScheduleId = item.AssignedCoaches()[0].ResourceScheduleId();
var seats = item.AssignedCoaches()[0].Seats();
//alert("in save" + this);
//viewModel.selectedItem(this);
$.ajax({
//url: "SaveTour",
url: "SaveTour/?seats=" + seats + "&rsID=" + resourceScheduleId,
data: ko.toJSON({ tour: ko.toJS(self.selectedItem) }),
type: "post",
contentType: "application/json",
success: function (result)
{
alert(result);
self.selectedItem(null);
}
});
}

self.selectItem = function () {
//self.selectedItem(this);
}

self.getDataFromServer = function (t) {
var tour = $("#tourCode").val();
var year = $("#year").val();
$.ajax({
url: "Search/?tour=" + tour + "&year=" + year ,
type: 'GET',
dataType: 'json',
success: function (result) {
ko.mapping.fromJS(result, {}, self);
self.page(0);
}
});
}

//Paging
self.page = ko.observable(0);
self.noOfPages = ko.observable(0);
self.nextPage = function () {
if (self.page() < (self.noOfPages()-1)) {
self.page(self.page() + 1);
self.GetClass(self.page());
} 
};
self.prevPage = function () {
if (self.page() >= 1) {
self.page(self.page() - 1);
}
};
self.currentPage = ko.computed(function () {
return self.TourSeriesDepartures().slice(self.page() * 10, (self.page() * 10) + 10);
});
self.noOfPages = ko.computed(function () {
return Math.ceil(self.TourSeriesDepartures().length / 10);
});
// returns a list of numbers for all pages
self.PageList = ko.computed(function () {
if (self.noOfPages() > 1) {
return Array.apply(null, { length: self.noOfPages() }).map(Number.call, Number);
}
});
self.goToPage = function (page) {
self.page(page);
};
// determines if page # is active returns active class
self.GetClass = function (page) {
return (page == self.page()) ? "active" : "";
}
}


$(document).ready(function () {
vm = new viewModel();
ko.applyBindings(vm);
});

这一定是网格创建者的疏忽。设置代码的方式是,模板直接绑定到所选项目,因此任何更改都会实时发生在原始模型上。有几种方法可以处理这一问题,但给定这个特定的示例代码,最简单的方法是在编辑时创建项或项值的备份,然后在cancel函数中恢复它们。

这里有一种方法可以做到这一点,方法是创建项目的克隆,并将其拼接回项目列表以替换修改后的项目。

self.edit = function (item) {
var clone = new State(item.id(), item.name(), item.shortName());
self.selectedBackup = clone;
self.selectedItem(item);
};
self.cancel = function () {
if(self.selectedBackup){
var item = self.selectedItem();
var index = self.list.indexOf(item);
self.list.splice(index, 1, self.selectedBackup);
}
self.selectedItem(null);
};

编辑:

在您的代码示例中,edit函数与cancel函数的敲除上下文不同。您还使用selectedItem仅引用所选行的离开数组中的第一个离开,但编辑按钮似乎引用了具有行跨度的整个组。因此,为了缓存/恢复正在修改的数据,我会将selectedItem设置为整个departureGroup,而不是出发。

self.templateToUse = function (item) {
return self.selectedItem() === item ? 'editTmpl' : 'itemsTmpl';
};
self.edit = function (item, event) {
var departureGroup = ko.contextFor(event.target).$parent;
self.selectedItem(departureGroup);
self.selectedItemCache(ko.mapping.toJS(departureGroup));
};
self.cancel = function (item) {
if (self.selectedItemCache) {
var departureGroup = ko.mapping.fromJS(self.selectedItemCache());
var index = self.TourSeriesDepartures.indexOf(departureGroup);
self.TourSeriesDepartures.splice(index, 1, departureGroup);
}
self.selectedItem(null);
};
self.save = function () {
var item = self.selectedItem().Departures()[0];
...

这是一把正在工作的小提琴:http://jsfiddle.net/3e9g0ros/

最新更新