2013-10-19 54 views
1

這裏的JS代碼:KNockoutJS使用jQuery數據表,不更新綁定行正確

function ProductViewModel() { 
    // Init. 
    var self = this; 
    self.products = ko.observableArray(); 
    self.singleProduct = ko.observable(); 
    var mappedProducts; 

    // Initialize table here. 
    $.getJSON("/admin/test", function(allData) { 
    mappedProducts = $.map(allData, function(item) { return new Product(item);}); 
    self.products(mappedProducts); 

    self.oTable = $('#products-table').dataTable({ 
     "aoColumns": [ 
     { "bSortable": false, "mDataProp": null, sDefaultContent: '' }, 
     {"mData": "name"}, 
     {"mData": "dealer"}, 
     {"mData": "cost"}, 
     {"mData": "price"}, 
     { "bSortable": false, sDefaultContent: '' } 
     ], 
    }); 
    }); 

    // Here i'm using the basic switch pattern, as from KO tutorials. 
    // This is intended for showing a single product form. 
    self.edit = function(product) { 
    self.singleProduct(product); 
    } 

    // This is intended to hide form and show list back. 
    self.list = function() { 
    self.singleProduct(null); 
    } 

    // This is the form save handler, actually does nothing 
    // but switch the view back on list. 
    self.doEdit = function(product) { 
    self.list(); 
    } 
} 



// My model. 
function Product(item) { 
    this.name = ko.observable(item.name); 
    this.dealer = ko.observable(item.dealer); 
    this.cost = ko.observable(item.cost); 
    this.price = ko.observable(item.price); 
    this.picture = ko.observable(); 
} 

這裏是我的標記:

<table id="products-table" class="table table-striped table-bordered table-hover"> 
     <thead> 
      <tr> 
      <th>Pic</th> 
      <th>Name</th> 
      <th>Dealer</th> 
      <th>Cost</th> 
      <th>Price</th> 
      <th>Actions</th> 
      </tr> 
     </thead> 

     <tbody data-bind="foreach: $parent.products"> 
      <tr> 
      <td><span data-bind='ifnot: picture'>-</span></td> 
      <td><a data-bind="text: name"></a></td> 
      <td><span data-bind='text: dealer'></span></td> 
      <td><span data-bind='text: cost'></span></td> 
      <td><span data-bind='text: price'></span></td> 
      <td> 
       <button data-bind='click: $root.edit'><i class='icon-pencil'></i> 
       </button> 
      </td> 
      </tr> 
     </tbody> 
     </table> 

當我點擊編輯按鈕,觸發$根。編輯處理程序,一個窗體顯示,因爲一個

<div data-bind='with: singleProduct'> 

綁定我已經作出。在這個綁定裏面我有一個表格,有一個

<input data-bind="value: name" type="text" id="" placeholder="Name" 
> class="col-xs-10 col-sm-5"> 

字段。

問題:當我編輯輸入字段中的值時,數據表中的相對行不會更新。我嘗試了一個沒有datatables插件的基本表,它確實有效,這意味着如果我更改了值,表中的行會正確更新。

這裏有什麼問題?

== ==編輯

我發現移動綁定點到固定的問題表TD,但我仍然無法找出原因。

  <tr> 
      <td data-bind="text: name"></td> 
      <!-- More columns... --> 
      </tr> 

上述代碼現在正常工作。爲什麼?

== == EDIT2現在

,我固定的第一個問題,談到第二。我實施了我的「save new」方法,如下所示:

self.doAdd = function(product) { 
    $.ajax("/product/", { 
     data: ko.toJSON({ product: product }), 
     type: "post", contentType: "application/json", 
     success: function(result) { alert('ehh'); } 
    }).then(function(){ 
     self.products.push(product); // <--- Look at this! 
     self.list(); 
    }); 
    } 

self.products.push(product);在成功處理程序正在更新我的產品可觀察。然後,一個新的行會自動添加到我的表中,這是個好消息。

壞消息是,只要我將新產品推入數組中,數據表控件(例如,搜索字段或可點擊排序箭頭)就會消失。爲什麼這樣!?

+0

是不更新您的問題,您self.products()不與新的值或該mappedProducts數組項更新?就像註釋mappedProducts不會反映更改一樣,因爲您還沒有將數據綁定到它,您將綁定到self.products observableArray。您需要手動更新mappedProducts陣列。 –

+0

KO Observables被更新,但不在表格內。無論如何檢查我最後的編輯,有新聞。 – brazorf

回答

1

你有沒有解決這個問題?

我一直有類似的問題的年齡。

最後,我的修補程序是使用ko.mapping.fromJS(實體)映射所有實體 - 然後將所有必需的依賴關係連接起來,並確保所有更改都流經我的模型。

+0

永遠不要解決這個問題,而DT開發人員在他們的論壇上表示,我們應該等待DT 1.10穩定,之前的版本將無法正常工作。順便說一句,你能在你的回覆中發表一個例子嗎? – brazorf

0

http://jsfiddle.net/zachpainter77/4tLabu56/

ko.bindingHandlers.DataTablesForEach = { 

     init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
      var nodes = Array.prototype.slice.call(element.childNodes, 0); 
      ko.utils.arrayForEach(nodes, function (node) { 
       if (node && node.nodeType !== 1) { 
        node.parentNode.removeChild(node); 
       } 
      }); 
      return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
     }, 
     update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 

      var value = ko.unwrap(valueAccessor()), 
      key = "DataTablesForEach_Initialized"; 

      var newValue = function() { 
       return { 
        data: value.data || value, 
        beforeRenderAll: function (el, index, data) { 

         if (ko.utils.domData.get(element, key)) { 

          $(element).closest('table').DataTable().destroy(); 
         } 
        }, 
        afterRenderAll: function (el, index, data) { 
         $(element).closest('table').DataTable(value.options); 
        } 

       }; 
      }; 

      ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext); 

      //if we have not previously marked this as initialized and there is currently items in the array, then cache on the element that it has been initialized 
      if (!ko.utils.domData.get(element, key) && (value.data || value.length)) { 
       ko.utils.domData.set(element, key, true); 
      } 

      return { controlsDescendantBindings: true }; 
     } 
    }; 

https://rawgit.com/zachpainter77/zach-knockout.js/master/zach-knockout.debug.js