У меня есть такая модель просмотра
function AppViewModel() {
var self = this;
self.blogUpdate = ko.observableArray();
}
var vm = new AppViewModel();
$(document).ready(function () {
$.getJSON('/Blog/GetUpdates?id=89', function (response) {
vm.blogUpdate = ko.observableArray(response);
ko.applyBindings(vm);
});
});
<table>
<thead>
<tr><th>First name</th><th>Last name</th></tr>
</thead>
<tbody data-bind = "foreach: blogUpdate">
<tr>
<td data-bind = "text: title"></td>
<td data-bind = "text: body"></td>
</tr>
</tbody>
</table>
У меня есть кнопка, которая открывает динамически созданный модальный / диалог с вводом формы. При отправке он отправляет обратно через ajax, а в функции успеха я пытаюсь отправить только что созданный JSON.
$.ajax({
type: 'POST',
global: false,
url: '/Blog/NewUpdate',
data: $form.serialize(),
success: function (response) {
vm.blogUpdate.push(response)
}
});
Если я обращаюсь к массиву, я вижу его там, но интерфейс не обновляется. В примерах, которые я вижу, на кнопке используется data-bind = "click: updateFunc". Но моя кнопка просто открывает модальное окно, которое позволяет вам вводить текст и сообщения ajax обратно.
Как я могу заставить это работать?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


https://jsfiddle.net/wvwh2x3n/1/
Я думаю, вам нужно проанализировать ответ, прежде чем нажимать на наблюдаемый массив. Вероятно, это выглядело бы как ...
success: function (response) {
var parsed = JSON.parse(response);
vm.blogUpdate.push(new BlogPost{ parsed.prop1, parsed.prop2 })
}
var BlogPost = function(prop1, prop2) {
var self = this;
self.prop1 = ko.observable(ko.utils.unwrapObservable(prop1));
self.prop2 = ko.observable(ko.utils.unwrapObservable(prop2));
}
Вы должны использовать data-bind = "modal: xyz", как показано на скрипке. Только не забывайте о работе по настройке привязок и т. д.
Что касается разметки из новых элементов ... Если у вас есть настройка observableArray, которую вы используете foreach, тогда это должен быть случай нажатия на нее. Если у вас есть какой-то код, мы можем видеть, что я стараюсь изо всех сил помочь.
я люблю нокаут: D
HTML
<div class = "row">
<div class = "col-sm-6 col-sm-offset-3">
<ul data-bind = "foreach: Users" class = "list-group hover">
<li class = "list-group-item">
<div class = "row">
<div class = "col-xs-6">
</div>
<div class = "col-xs-2">
</div>
<div class = "col-xs-4 text-right">
<a href = "#" data-bind = "click: $parent.EditUser">Show modal</a> |
</div>
</div>
</li>
</ul>
</div>
</div>
<div data-bind = "modal: UserBeingEdited" class = "fade" role = "dialog" tabindex = "-1">
<form>
<div class = "modal-header">
<a class = "close" data-dismiss = "modal">×</a>
<h3>User Details</h3>
</div>
<div class = "modal-body">
<div class = "form-group">
<label for = "NameInput">Name</label>
<input type = "text" class = "form-control" id = "NameInput" placeholder = "User's name" data-bind = "value: UserBeingEdited() && UserBeingEdited().Name, valueUpdate: 'afterkeydown'">
</div>
<div class = "form-group">
<label for = "AgeInput">Age</label>
<input type = "text" class = "form-control" id = "AgeInput" placeholder = "User's age" data-bind = "value: UserBeingEdited() && UserBeingEdited().Age, valueUpdate: 'afterkeydown'">
</div>
<!-- /ko -->
</div>
<div class = "modal-footer">
<button type = "button" data-dismiss = "modal" class = "btn btn-default">Cancel</button>
<button type = "submit" class = "btn btn-primary">Save Changes</button>
</div>
</form>
</div>
CSS
/**** These styles are here to override the styles in 'bootstrap-modal-bs3patch.css' ****/
$screen-sm-min = 768px; //<== Standard Bootstrap width
.modal {
left: 25%;
width: 50% !important;
@media screen and (-webkit-min-device-pixel-ratio:0) {
/* Safari and Chrome */
left: 50%;
width: 500px;
}
@media (max-width: $screen-sm-min) {
left: 0;
width: 100% !important;
}
}
JS
ko.bindingHandlers['modal'] = {
init: function(element, valueAccessor, allBindingsAccessor) {
var allBindings = allBindingsAccessor();
var $element = $(element);
$element.addClass('hide modal');
if (allBindings.modalOptions && allBindings.modalOptions.beforeClose) {
$element.on('hide', function() {
var value = ko.utils.unwrapObservable(valueAccessor());
return allBindings.modalOptions.beforeClose(value);
});
}
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (value) {
$(element).removeClass('hide').modal('show');
} else {
$(element).modal('hide');
}
}
};
/* ViewModel for the individual records in our collection. */
var User = function(name, age) {
var self = this;
self.Name = ko.observable(ko.utils.unwrapObservable(name));
self.Age = ko.observable(ko.utils.unwrapObservable(age));
}
/* The page's main ViewModel. */
var ViewModel = function() {
var self = this;
self.Users = ko.observableArray();
// The instance of the user currently being edited.
self.UserBeingEdited = ko.observable();
// Used to keep a reference back to the original user record being edited
self.OriginalUserInstance = ko.observable();
self.EditUser = function(user) {
// Keep a copy of the original instance so we don't modify it's values in the editor
self.OriginalUserInstance(user);
// Copy the user data into a new instance for editing
self.UserBeingEdited(new User(user.Name, user.Age));
}
}
var viewModel = new ViewModel();
// Populate the ViewModel with some dummy data
for (var i = 1; i <= 10; i++) {
var letter = String.fromCharCode(i + 64);
var userName = 'User ' + letter;
var userAge = i * 2;
viewModel.Users.push(new User(userName, userAge));
}
// Let Knockout do its magic!
ko.applyBindings(viewModel);
На самом деле это сработало. По какой-то причине я ожидал, что он появится вверху, но вместо этого он появился внизу. Необходимо использовать
unshiftвместоpush.