你能帮助我调试为什么当我打电话给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>
答案 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)
有两种方法可以做到:
splice
replace
第一个是在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)即可更新用户界面。