2017-10-25 7 views
1

私はこのブログに基づいてインプレイスグリッド編集を作成しています。InPlaceグリッドの編集、キャンセルが失敗します。

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

他のすべてがキャンセル]ボタンがまだ新しい値でUIを更新除き、[OK]を動作します。

どうすれば修正できますか? 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); 
     }); 

答えて

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

編集:あなたのコード例で

ノックアウトコンテキストは、それがキャンセル機能のためであるよりも、編集機能のために異なっています。 selectedItemを使用して、選択した行の出発配列の最初の出発点のみを参照していますが、編集ボタンは行スパンでグループ全体を参照しているようです。したがって、変更されているデータをキャッシュ/リストアするためには、departitGroupの代わりに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/

+0

だから私のUIは、ネストされたコレクション内の(つまり2レベルの深さだ)子要素にバインドされています。ここで「アイテム」にスプライスする最も良い方法は何ですか?例えばレベル1、レベル2、レベル3、私の場合のアイテムはレベル3の行です。 – user8808262

+0

@ user8808262編集機能はどのように機能しますか?編集中のモデルへの参照がありますか? –

+0

はいレベル2(レベル3の配列を含む)への参照があり、レベル3の値を更新/キャンセルする必要があります。 – user8808262

関連する問題