observableArray替换不更新UI

时间:2014-03-18 16:58:26

标签: javascript knockout.js ko.observablearray

你能帮助我调试为什么当我打电话给replace时,它没有被反映在UI上。结帐功能中的******是我调用replace的地方。在索引中,我循环遍历我的observableArray以显示项目。

当我刷新页面时,当前将反映UI。

谢谢!

JS

$(function(){
  ko.applyBindings(new ViewModelBooks());
});


function Book(title, user_id, book_id)
{
  this.title = ko.observable(title);
  this.user_id = ko.observable(user_id);
  this.book_id = ko.observable(book_id);
}

function ViewModelBooks(){
  var self = this;
  self.library = ko.observableArray();
  getBooks();

  // Click event for checking out a book
  self.checkOutBook = function(obj){
    checkOutBook(obj, "Book");
  };


  function checkOutBook(book, list_name)
  {
    // Get current user
    alert(self.library.indexOf(book));
    var user_id = $().SPServices.SPGetCurrentUser({
      fieldName: "ID",
      debug: false
    });
    // Prep for update get all books
    var item_type = getItemType(list_name);

    var item = {
      "UserID": user_id,
    }

    var updated_book = book;
    updated_book.user_id = user_id;

    getListItemWithId(book.book_id(), function(data){   
        var temp_uri = data.__metadata.uri;
        $.ajax({
          url: temp_uri,
          type: "POST",
          contentType: "application/json",
          data: JSON.stringify(item),
          headers: {
                "Accept": "application/json;odata=verbose",
                "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                "X-HTTP-Method": "MERGE",
                "If-Match": data.__metadata.etag
            },
          success: function (data){
            console.log('Success!');
            self.library.replace(book, updated_book); ***************
          },
          error: function(data){
            alert('Error has occured');
          }
        });
    }, function (data) { alert('Error has occured'); });
  }

// Query all books
  function getBooks(){
      var url = 'http://portal.internal.urs.org/tools_services/training_library/_vti_bin/listdata.svc/Book';
      $.getJSON(url, function(data){
        for (var i = 0; i < data.d.results.length; i++){
            var book = data.d.results[i];
            var user_id= null;

            if (book.UserID != null){
              user_id = book.UserID;
            }
            self.library.push(new Book(book.Title, user_id, book.Id));
        }
      });
  }

HTML

<table class="LibraryTable">
    <thead><tr>
    <th>Title</th><th>Check Out</th>
    </tr></thead>
    <tbody data-bind="foreach: library">
        <tr><td data-bind="text: title"></td>
            <td>
                <span data-bind="ifnot: user_id">
                    <button class="btn_checkout" type="button" 
                    data-bind="click: $parent.checkOutBook">Check Out</button>
                </span>
                <span data-bind="if: user_id">
                    Checked Out
                </span>
            </td>
        </tr>
    </tbody>
</table>

4 个答案:

答案 0 :(得分:2)

我建议使用observableArrays为您实现的标准拼接方法

self.library.splice(self.library.indexOf(book), 1, updated_book);

此文档和所有其他可观察数组实现的文件是here

答案 1 :(得分:0)

在我的代码中,我设置了updated_book.user_id错误的
它应该是updated_book.user_id(user_id)

答案 2 :(得分:0)

有两种方法可以做到:

  1. 使用splice
  2. 使用replace
  3. 第一个是在Knockout文档中记录的,但第二个不是:Knockout Obervable Arrays Docs。但是,如果你查看源代码,你会发现两个函数都已实现(至少在KO 3.0中,我不知道以前的版本中是否缺少replace)。

    此操作的语法是:

    obsArray.splice(
      index,      // at index
      1,          // remove 1 element
      newElement  // and add all the elements passed as the following parameters
    );
    
    
    obsArray.replace(
      originalElement,   // replace the element passed as 1st parameter from the array
      newElement         // with the eleemnt passed as second parameter
    );
    

答案 3 :(得分:0)

问题是book和updated_book都指向同一个对象。在checkOutBook函数中:

var updated_book = book;          // book and updated_book point to the same obj,
updated_book.user_id = user_id;   // so this also sets book.user_id 

如果您在分配user_id后使用Firebug或Chrome调试器查看其值,您会看到book.user_id和updated_book.user_id都具有新值。

ObservableArrays不会跟踪其内容属性的变化。它们仅跟踪对阵列本身的更改,即添加项目和删除项目。如果您希望更改项目的属性以反映在UI中,您可以采用两种方式:

从数组中删除该项目并重新添加更改后的版本。

将每个数组项设为ko.observable。

我认为第二种方法更直接,因为只需设置book.user_id(user_id)即可更新用户界面。