javascript - Knockout.js 通过 ajax 调用将项目添加到 foreach

标签 javascript knockout.js

我有一个像这样的 View 模型

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 发回。

我怎样才能让它发挥作用?

最佳答案

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"如 fiddle 中所示。只是不要忘记所有绑定(bind)设置工作等。

关于新项目的标记...如果您有一个 foreach 设置的 observableArray,那么它应该只是推送到它的情况。如果您有一些代码,我们可以看到,我会尽力提供帮助。

我喜欢 knockout :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);

关于javascript - Knockout.js 通过 ajax 调用将项目添加到 foreach,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49332448/

相关文章:

javascript - 如果以编程方式更改模型,ko 不会更新绑定(bind)控件

javascript - 如果某些 <tr> 不可见,则交替行颜色

javascript - 我正在尝试使用复选框获取多选下拉列表,在填充项目和获取 allChecked 工作时遇到一些问题

javascript - 在 AJAX 中将数据与 FormData 作为一个对象一起发送

javascript - 将对象数组从 JavaScript 发送到 C# Controller

javascript - 通过 javascript 打开 facebook 连接窗口?

javascript - 您可以在消息内使用 Knockout 自定义验证器中的参数吗?

javascript - php中的子串js

javascript - 为什么我的 UI/Draggable 'create' 事件被传递了一个空的 'ui' 对象?

javascript - knockout html 绑定(bind)与内部的另一个绑定(bind)