InPlace网格编辑,取消失败

时间:2017-10-25 18:11:00

标签: knockout.js

我正在关注此博客以创建就地网格编辑。

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

其他一切正常,但“取消”按钮仍然使用新值更新UI。

我该如何解决? Hpw我获取旧值并在用户单击取消时使用原始值更新字段吗?

谢谢!

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);
        });

1 个答案:

答案 0 :(得分:0)

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

这是通过创建项目的克隆并将其拼接回项目列表以替换修改后的项目来实现此目的的一种方法。

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);
};

修改

在您的代码示例中,编辑功能的knockout上下文与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/