I have a Knockout viewmodel which is being created by the ko.mapping plugin.
var infoNeeded = [{
"ProductPKUID":10069,
"ProductID":"SW42",
"ProductName":"Display Name of Product",
"Quantity":1,
"NeededInfo":[
{
"InfoTypeNeeded":0,
"InfoGathered":null
},
{
"InfoTypeNeeded":1,
"InfoGathered":null}]}];
infoNeeded = ko.mapping.fromJS(infoNeeded);
Note that in this example, the viewmodel only contains one product, but it's an array that could contain more. That viewmodel is being applied to this block of HTML, which seems to be working.
<div id="additionalInfoNeeded" data-bind="foreach: infoNeeded">
<span data-bind="text: ProductID"></span> - <span data-bind="text: ProductName"></span>
<span data-bind="visible: Quantity > 1, text: '(Qty: ' + Quantity + ')'"></span>
<div data-bind="foreach: NeededInfo">
<div>
Needs Info Type: <span data-bind="text: InfoTypeNeeded"></span>
<div data-bind="if: (InfoTypeNeeded() === 1)">
<species-edit params="value: $data, prodID: $parent.ProductID()"></species-edit>
</div>
</div>
</div>
</div>
Notice I am using a custom element (species-edit) there if the information needed for this product in the array is infoType = 1. I want the species-edit element to grab a list of species from the server which relate to this productID, then allow the user to pick from that list. Then I want my main viewmodel to be able to see the selected species. The species json coming back from the server looks like this.
[{"ID":1,"Name":"BLUE CRAB","Chosen":false},{"ID":2,"Name":"EEL","Chosen":false},{"ID":5,"Name":"INSHORE FISH","Chosen":false},{"ID":6,"Name":"OFFSHORE FISH","Chosen":false},{"ID":7,"Name":"OTHER","Chosen":false},{"ID":8,"Name":"SHARK","Chosen":false},{"ID":9,"Name":"SHRIMP OR PRAWN","Chosen":false},{"ID":12,"Name":"AMERICAN SHAD","Chosen":false},{"ID":28,"Name":"SHELLFISH(OYSTER,CLAM,MUSSEL","Chosen":false}]
Here is my species-edit.html:
<div>
<div>What type of species will the customer attempt to take?</div>
<div>Insert species valid for product <span data-bind="text: productID"></span> here.
</div>
List of species is <span data-bind="text: data.speciesList().length"></span>
<div class="speciesList" data-bind="if: data.speciesList().length > 0">
<div class="header">
<div>Unselected</div>
<div>Selected</div>
</div>
<div data-bind="foreach: data.speciesList">
<input type="checkbox" data-bind="checked: Chosen"/>
<label data-bind="text: Name"></label>
</div>
</div>
</div>
And my species-edit.js:
define(['knockout'],
function (ko) {
function ProductSpeciesSelectionViewModel(params) {
var self = this;
self.productID = params.prodID;
self.data = params.value;
self.data.speciesList = ko.observableArray([]);
self.data.speciesList.push({Name: "Herpdy Derp", Chosen: false});
console.debug("gonna ask for " + window.applicationBaseUrl + "AdditionalInformation/SpeciesFor/" + self.productID());
var jqxhr = $.getJSON(window.applicationBaseUrl + "AdditionalInformation/SpeciesFor/" + self.productID())
.success(function (data, status, xhr) {
console.debug(data);
self.data.speciesList.push({ Name: "Test", Chosen: false });
})
.error(function() { alert("Error in Species Grabber!"); })
.complete(function() { console.log("Fetch Complete"); });
}
return ProductSpeciesSelectionViewModel;
});
If you notice in the species-edit viewmodel, I'm not actually using the species list returned by the server. I'm initializing the list with a "Herpdy Derp" specie, and then when the getJSON call is successful I'm adding a "Test" specie. However, the custom element isn't displaying either of those. It is receiving and displaying the productID, and it is receiving a list of length==1 (Should be 2?), but not rendering any property of the list item(s). Here is the resultant text on the screen.
SW42 - Display Name of Product
Needs Info Type: 0
Needs Info Type: 1
What type of species will the customer attempt to take?
Insert species valid for product SW42 here.
List of species is 1
Unselected
Selected
I am confused by this. It sees the speciesList as having a length of one, but is not rendering the one item. I'm also confused why that list is not length == 2, since the getJSON call has succeeded by this point.
This is my first time using custom knockout elements and I clearly haven't gotten it right. Any help would be appreciated.
<div data-bind="if: (InfoTypeNeeded() === 1">"if: (InfoTypeNeeded() === @((int)InfoCollector.Species))", which asp.net was translating into"if: (InfoTypeNeeded() === 1)". I missed the trailing parenthesis when pasting, but it's there. Will update original post.