Knockout.js从ajax调用

时间:2018-03-17 04:15:53

标签: javascript knockout.js

我有一个像这样的视图模型

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

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

1 个答案:

答案 0 :(得分:2)

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”,如小提琴中所示。只是不要忘记所有绑定设置工作等。

关于来自新项目的标记...如果你有一个foreistic的observableArray设置,那么它应该只是一个推动它的情况。如果您有一些代码我们可以看到生病尽力帮助。

我喜欢淘汰赛: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);