I'm using Knockout.js 2.2.1 and Breeze 1.3.5 to retrieve and display some data but the results are way off. The data comes from a self referencing table. As far as I can tell Knockout seems to think that the Children property of each item should return the entire array and not the actual children of item. What am I doing wrong?
UPDATE 1: I created a fiddle and I get the expected results but it doesn't use breeze.js. So perhaps this is a breeze.js issue? Something of note in the fiddle is that Children and Name are both referenced without parenthesis whereas in my full blown application breeze.js seems to be converting them to the proper observables* and requiring parenthesis for the Name.
Current result:
Apparel
- Apparel
Art
- Art
Books
- Books
Movies
- Movies
test
- test
Blu-ray
- Blu-ray
DVD
- DVD
Animation
- Animation
Accessories
- Accessories
Expected result:
Apparel
- Accessories
Art
- Animation
Books
Movies
- Blu-ray
- DVD
test
VM:
var vm = {
categories: ko.observableArray()
};
Knockout.js markup:
<div data-bind="foreach: categories">
<div data-bind="text: Name"></div>
<div data-bind="foreach: Children">
<div data-bind="text: ' - ' + Name()"></div>
</div>
</div>
Breeze code:
var query = breeze.EntityQuery.from("Category")
.orderBy("ParentCategoryId, Name")
.expand("Children");
_entityManager
.executeQuery(query)
.then(function (data) {
vm.categories.removeAll();
console.log("here: " + data.results.length); -- produces 9
data.results.forEach(function (item) {
vm.categories.push(item);
});
})
.fail(function (error) { console.log("Error: " + error); });
Breeze query results:
[ { "$id" : "1",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 5,
"Children" : [ { "$id" : "2",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 6,
"Children" : [ ],
"CreatedOn" : "2013-05-31T11:29:11.860",
"Description" : "Accessories",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "Accessories",
"ParentCategory" : { "$ref" : "1" },
"ParentCategoryId" : 5
} ],
"CreatedOn" : "2013-05-31T11:28:37.677",
"Description" : "Apperal",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "Apparel"
},
{ "$id" : "3",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 3,
"Children" : [ { "$id" : "4",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 4,
"Children" : [ ],
"CreatedOn" : "2013-05-31T11:25:46.333",
"Description" : "Animation",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "Animation",
"ParentCategory" : { "$ref" : "3" },
"ParentCategoryId" : 3
} ],
"CreatedOn" : "2013-05-31T11:25:30.250",
"Description" : "Art",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "Art"
},
{ "$id" : "5",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 1,
"Children" : [ ],
"CreatedOn" : "2013-05-13T17:14:15.880",
"Description" : "Books",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "Books"
},
{ "$id" : "6",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 2,
"Children" : [ { "$id" : "7",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 7,
"Children" : [ ],
"CreatedOn" : "2013-05-31T11:31:05.710",
"Description" : "Blu-ray",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "Blu-ray",
"ParentCategory" : { "$ref" : "6" },
"ParentCategoryId" : 2
},
{ "$id" : "8",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 8,
"Children" : [ ],
"CreatedOn" : "2013-05-31T11:31:15.000",
"Description" : "DVD",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "DVD",
"ParentCategory" : { "$ref" : "6" },
"ParentCategoryId" : 2
}
],
"CreatedOn" : "2013-05-14T12:13:36.570",
"Description" : "DVD's & Blu-ray",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "Movies"
},
{ "$id" : "9",
"$type" : "SR.Data.Models.Domain.Category, SR.Data",
"CategoryId" : 11,
"Children" : [ ],
"CreatedOn" : "2013-06-03T15:32:50.023",
"Description" : "test",
"IsDeleted" : false,
"IsPublished" : true,
"Name" : "test"
},
{ "$ref" : "7" },
{ "$ref" : "8" },
{ "$ref" : "4" },
{ "$ref" : "2" }
]
Category entity:
public class Category
{
public Category() { }
public virtual int CategoryId { get; set; }
public virtual int? ParentCategoryId { get; set; }
public virtual int? PictureId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual bool IsPublished { get; set; }
public virtual bool IsDeleted { get; set; }
public virtual DateTime CreatedOn { get; set; }
public virtual Category ParentCategory { get; set; }
public virtual Picture Picture { get; set; }
public virtual ICollection<Category> Children { get; set; }
}
Category mapping:
modelBuilder.Entity<Category>().HasKey(a => a.CategoryId);
modelBuilder.Entity<Category>().HasOptional(x => x.Picture).WithMany().HasForeignKey(x => x.PictureId);
modelBuilder.Entity<Category>().HasOptional(x => x.ParentCategory).WithMany().HasForeignKey(x => x.ParentCategoryId);
modelBuilder.Entity<Category>().HasMany(x => x.Children).WithOptional().HasForeignKey(x => x.ParentCategoryId);
Category table: