简体   繁体   中英

Knockout - Having trouble accessing nested JSON data

There's several similar questions about accessing nested JSON in Knockout, but I can't get this to work. I'm sure it's something simple. I'd like to do this without the knockout.mapping plugin if possible.

EDIT:

Here's a fiddle I put together. https://jsfiddle.net/ym0h4w49/14/

I can't get this to actually render the dom like it does on the site I'm working on, but the console.log shows the singleContact Object. Uncomment the self.tags to see how it breaks.

Given this JSON response with nested objects:

{
  "id": 1,
  "firstname": "Ina",
  "lastname": "Church",
  ... etc ...
  "registered": "2014-10-06T11:22:51 +05:00",
  "tags": [
    {
      "id": "t1",
      "contactId": 1,
      "tagLabel": "wguldin"
    }
  ]
}

How would I access the tags for this person? I've tried the following.

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 + '?_embed=tags&_embed=reminders',
        dataType: 'json',
        success: function(data) {
          var contactData = new singleContact(data);
          self.contact(contactData);
        }
      });
  }

  self.getContact(self.contactID());
};

This view model creates a new singleContact, which processes the data like so:

function singleContact(data) {
  var self = this;

  self.firstName = data.firstname;
  self.lastName = data.lastname;
  ...

  self.tags = ko.observableArray(ko.utils.arrayMap(self.tags, function(tag) {
      return new tag(tag.id, tag.contactID, tag.tagLabel);
  }));
};

Which should then pass in the tag information to this function, I think.

function tag(id, contactID, tagLabel) {
    var self = this;

    self.id = id;
    self.contactID = contactID;
    self.tagLabel = tagLabel;
}

But when I console.log singleContact, a weird function thing appears as the tags value.

singleContact的console.log

I'm not sure if that means its there or not, but it doesn't render in the DOM using this markup:

<!-- ko foreach: contact -->
  <h1 data-bind="text: firstName"></h1>

  ...

  <!-- ko foreach: tags -->
  <p data-bind="text: tag.tagLabel"></p>
  <!-- /ko -->

<!-- /ko -->

Thanks!

Try something like this

view:

<!-- ko foreach: contact -->
  <h1 data-bind="text: firstName"></h1>
  <!-- ko foreach: tags -->
  <p data-bind="text:tagLabel"></p>
  <!-- /ko -->
<!-- /ko -->

viewModel:

var json = {
  "id": 1,
  "firstname": "Ina",
  "lastname": "Church",
  "registered": "2014-10-06T11:22:51 +05:00",
  "tags": [
    {
      "id": "t1",
      "contactId": 1,
      "tagLabel": "wguldin"
    }
  ]
}

function tag(id, contactID, tagLabel) {
    var self = this;
    self.id = id;
    self.contactID = contactID;
    self.tagLabel = tagLabel;
}

function singleContact(data) {
  var self = this;
  self.firstName = data.firstname;
  self.lastName = data.lastname;
    var con =  ko.utils.arrayMap(data.tags, function(item) { // use item rather tag which may give different meaning & loop through data.tags 
      return new tag(item.id, item.contactID, item.tagLabel);
  });
  self.tags = ko.observableArray(con); 
};

function detailViewModel() {
  var self = this;
  self.contact = ko.observableArray([]);
  self.contact([new singleContact(json)]); // use [] here to make it array
};
ko.applyBindings(new detailViewModel())

sample working fiddle up here

Check here for your working fiddle sample

i think thats fine i think all you need to do is change the knockout binding

<!-- ko foreach: contact -->
  <h1 data-bind="text: firstName"></h1>

  ...

  <!-- ko foreach: tags() -->
  <p data-bind="text: tag().tagLabel"></p>
  <!-- /ko -->

<!-- /ko -->

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM