I have a large XML file (converted to JSON) that consists of multiple repeating sections with the same structure. Each section has a set of identically structured attribues (XML to JSON conversion moves all attributes into an object called myAttributes) in addition to the section specific properties. My objective is to be able to read existing XML and generate new XML.
I tried to use the mapping plugin, put it only allows me to read XML, not generate it, plus there are multiple interdependencies between object elements.
I figured that the best way to work around this is to pre-define a set of objects that match small sections of the XML. When assembled together, these objects would be able to generate XML structure that i need. This way I can either loop though the JSON array that I generated from XML, populate objects that I pre-defined with appropriate data and append them to my viewModel (lets say 10 alerts, 3 actions, 6 metric groupings, etc). Generating XML from pre-defined objects should also be easy.
However, due to my general inexperience with both JavaScrip and KnockoutJS, I am having a very hard time figuring this one out.
// Main Top Level Management Module Object
function ManagementModule(data) {
this.myAttributes = new Object();
this.myAttributes.Name = ko.observable(data.Name);
this.myAttributes.IsActive = ko.observable(data.IsActive);
this.myAttributes.DescriptionContentType = ko.observable(data.DescriptionContentType);
this.myAttributes.Description = ko.observable(data.Description);
// There are other object specific properties, but I omitted them for now
}
// New Alert Object. It will be deep in the hierarchy of the main top level object
// but for now i will make it top level for test purposes.
function Alert(data) {
this.myAttributes = new Object();
this.myAttributes.Name = ko.observable(data.Name);
this.myAttributes.IsActive = ko.observable(data.IsActive);
this.myAttributes.DescriptionContentType = ko.observable(data.DescriptionContentType);
this.myAttributes.Description = ko.observable(data.Description);
// There are other object specific properties, but I omitted them for now
}
// View Model
function myModel() {
var self = this;
self.ManagementModule = ko.observableArray();
self.Alerts = ko.observableArray();
};
var myViewModel = new myModel();
Then I loop through my JSON and try to append things to the view model… and this is where things do not work right. Perhaps because I misunderstand the objects…
$.getJSON("/getXML", function (data) {
for (var key in data) {
// Do something here
}
// This seems to work OK. There is only 1 so, I just
// set it.
myViewModel.ManagementModule(data['myAttributes']);
for (var i = 0; i < data['DataGroups']['DataGroup'].length; i++) {
var current = data['DataGroups']['DataGroup'][i];
if(current['AlertBase']) {
var AlertBase = current['AlertBase'];
// There are multiple Alarts
for (var i = 0; i < AlertBase.length; i++) {
myViewModel.Alerts.push(Alert(AlertBase[i].myAttributes));
}
}
};
ko.applyBindings(myViewModel);
});
This kinda-sorta works…. When I try to bind to it
<div data-bind="text: Alerts.myAttributes.Name"></div>
<div data-bind="text: ManagementModule.myAttributes.Name"></div>
it is not working. If i bind like this:
<div data-bind="text: myAttributes.Name"></div>
it outputs both, myViewModel.ManagementModuleName.myAttributes.Name and the very last one myViewModel.Alert.myAttributes.Name joined together.
What am I doing wrong? How can I assemble a viewModel out of multiple nested objects?
UPDATE: Just realized I was binding incorrectly, but that still produces a bunch of
myViewModel.ManagementModuleName.myAttributes.Name and the very last one myViewModel.Alert.myAttributes.Name joined together
<div data-bind="foreach: Alerts()">
<div data-bind="text: myAttributes.Name"></div>
</div>
And I think I solved it…
myViewModel = new ManagementModule(data['myAttributes']);
myViewModel.Alerts = ko.observableArray();
myViewModel.Alerts.push(new Alert(AlertBase[i].myAttributes));
<div data-bind="text: myAttributes.Name"></div><br />
<div data-bind="foreach: Alerts()">
<div data-bind="text: myAttributes.Name"></div>
</div>
For starters, you are referencing observableArrays as if they we observables. You need a data-bind=foreach: Alarms() in there someplace.
OK: See if this jsFiddle helps you: http://jsfiddle.net/8QVe6/
Note that I made the properties camelCased (i.e. managementModule).