2017-10-25 7 views
1

이 블로그에 따라 inplace 표 편집을 만듭니다. 다른InPlace Grid Edit, 취소가 실패합니다.

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

답변

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을 사용하여 선택한 행의 departures 배열에서 첫 번째 출발 만 참조하지만 편집 버튼은 행 그룹과 함께 전체 그룹을 참조하는 것으로 보입니다. 따라서 캐시 된/복원 할 데이터를 복원하려면 departIture 전체를 출발지 대신 selectedItem을 설정합니다. http://jsfiddle.net/3e9g0ros/

+0

그래서 내 UI가 중첩 된 컬렉션 (즉, 2 레벨 깊이의) 자식 요소에 바인딩 :

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]; ... 

는 다음 작업 바이올린입니다. 여기서 "항목"에 이어지는 가장 좋은 방법은 무엇입니까? 예 : 레벨 1, 레벨 2, 레벨 3 및 내 경우의 항목은 레벨 3의 행입니다. – user8808262

+0

@ user8808262 편집 기능은 어떻게 작동합니까? 편집중인 모델에 대한 참조가 있습니까? –

+0

예 레벨 2 (레벨 3의 배열 포함)에 대한 참조가 있으며 레벨 3의 값을 업데이트/취소해야합니다. – user8808262