Knockout.js-试图将JSON添加到视图模型中是未定义的



我已经看到了一些问题,但我仍然不知道我做错了什么。

我想做的是从服务器上取回一个JSON对象,它看起来像这样:

{
  "firstname": "Blanchard",
  "lastname": "Buckner",
  ...
}

视图模型执行AJAX调用,数据似乎设置正确。但是,当我试图将它传递给我的singleContact函数以绑定到视图时,什么也没发生。

我是Knockout的新手,所以我确信我犯了一个很容易的错误,但我已经试了一段时间,但什么都没用。

// Binds json db data to each contact.
function singleContact(data) {
  var self = this;
  self.firstName = data.firstname;
  self.lastName = data.lastname;
  self.fullName = ko.computed(function() {
      return self.firstName + " " + self.lastName;    
  }, self);
  self.image = data.image;
  self.position = data.position;
  self.company = data.company;
};
function detailViewModel(contactID) {
  var self = this;
  self.contactID = ko.observable(contactID);
  self.contact = ko.observableArray([]);
  self.getContact = function(id) {
    $.ajax({
      type: 'GET',
      url: 'http://localhost:3000/contacts/' + id,
      dataType: 'json',
      success: function(data) {
        console.log(singleContact(data)); <---- Always Undefined. The data is a JSON object.
      }
    });
  }
  self.getContact(self.contactID());
};

编辑:这是标记,应该是第一次包含的。

<!-- ko foreach: contact -->
  <img class="contact__image" data-bind="attr:{src: image, alt: fullName}" />
  <h1 data-bind="text: fullName"></h1>
  <h2>
    <span data-bind="text: position"></span>,
    <span data-bind="text: company"></span>
  </h2>
  <h5>Notes on <span data-bind="text: fullName"></span></h5>
  <p></p>
<!-- /ko -->

您需要使用new关键字来创建单个Contact对象:

var contact = new singleContact(data);

然后可以将其分配给detailViewModel上的可观察对象:

self.singlecontact(contact);

我还建议您对viewModel使用Upper Camelcase。即DetailViewModel,而不是使用面向对象编程时在任何其他语言中使用的detailViewModel

这里是一个工作示例。缺少的是,您没有将创建的模型推入observableArray。我已经证明,你可以得到一系列的结果,并很容易地把它们推进去。

function DetailViewModel(id) {
  var self = this;
  self.contacts = ko.observableArray([]);
  // make ajax call.. mocking here
  var results = ajax();
  results.forEach(function(result) {
    self.contacts.push(new Contact(result));
  });
}
function Contact(data) {
  var self = this;
  self.firstName = data.firstName;
  self.lastName = data.lastName;
  self.company = data.company;
  self.position = data.position;
  self.image = data.image;
  self.fullName = ko.pureComputed(function() {
    return self.firstName + ' ' + self.lastName;
  });
  return self;
}
function ajax() {
  return [{
    firstName: 'Rich',
    lastName: 'Hickey',
    company: 'Cognitect',
    position: 'CTO',
    image: 'http://gotocon.com/dl/photos/speakers/Rich%20Hickey2.jpg'
  }, {
    firstName: 'Scott',
    lastName: 'Hanselman',
    company: 'Microsoft',
    position: 'Architect',
    image: 'http://www.globalnerdy.com/wordpress/wp-content/uploads/2009/09/scott_hanselman.jpg'
  }];
}
$(function() {
  ko.applyBindings(new DetailViewModel());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<!-- ko foreach: contacts -->
<div>
  <img class="contact__image" data-bind="attr:{src: image, alt: fullName}" style="width: 100px; height: 150px" />
  <h1 data-bind="text: fullName"></h1>
  <h2>
    <span data-bind="text: position"></span>,
    <span data-bind="text: company"></span>
  </h2>
  <h5>Notes on <span data-bind="text: fullName"></span></h5>
</div>
<!-- /ko -->

最新更新