Reputation: 598
I'am trying to display product list from database using signalr and knockout.js. But without any result. Could anyone tell me what I'am doing wrong or where I have mistake? I will be very grateful for helping me. This is the view:
<div class="products">
<div class="row" data-bind="template: { name: 'productTemplate', foreach: products }">
</div>
<span class="messageClass" style="color: red;"></span>
</div>
<script type="text/html" id="productTemplate">
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<div class="caption">
<h3 data-bind="text: name"></h3>
</div>
</div>
</div>
</script>
This is the script:
<script>
$(function () {
function productViewModel(id, name) {
this.productId = id;
this.name = ko.observable(name);
var self = this;
}
function productListViewModel() {
this.hub = $.connection.voteHub;
this.products = ko.observableArray([]);
var products = this.products;
this.init = function () {
this.hub.server.getAllProducts();
}
this.hub.client.getAllProducts = function (allProducts) {
var mappedProducts = $.map(allProducts, function (item) {
return new productViewModel(item.productId, item.name)
});
products(mappedProducts);
}
}
var vm = new productListViewModel();
ko.applyBindings(vm);
$.connection.hub.start(function () {
vm.init();
});
});
</script>
Here is the hub method to get all products:
public void GetAllProducts()
{
VoteViewModel viewModel = new VoteViewModel();
viewModel.Products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
if (viewModel.Products != null)
{
// TODO: pomyslec nad wysylaniem listy a nie tablicy!
Clients.All.getAllProducts(viewModel.Products.ToArray());
}
}
If I put on my hub code like this, it will work well (taken from demo app):
VoteViewModel vm = new VoteViewModel();
vm.Products = new List<Product>() { new Product() { Name = "Sample", Id = 1 } };
Clients.All.getAllProducts(vm.Products.ToArray());
My code which look like this don't work though. (i don't know why, maybe because my Product object from db, has more variables?):
VoteViewModel viewModel = new VoteViewModel();
viewModel.Products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
Clients.All.getAllProducts(viewModel.Products.ToArray());
Here is code from my Product class: (dbcontext class)
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Required]
public string ImagePath { get; set; }
public virtual ICollection<Vote> Votes { get; set; }
I made new ProductViewModel class which looks like this:
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string ImagePath { get; set; }
public int VotesAmount { get; set; }
}
And then bind all data from db to that model, and then return List and IT WORKS NOW!, but I really don't understand why I can't just take list of products from database and send it to signalr client side (like I tried to do it before).
List<ProductViewModel> prods = new List<ProductViewModel>();
List<Product> products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
foreach (var item in products)
{
ProductViewModel prod = new ProductViewModel()
{
Id = item.Id,
Name = item.Name,
Description = item.Description,
ImagePath = item.ImagePath,
VotesAmount = item.Votes.Count()
};
prods.Add(prod);
}
Clients.All.getAllProducts(prods.ToArray());
Upvotes: 3
Views: 4214
Reputation: 1547
Your code is absolutely working fine. Please check if you have the referrence to the following files.
<script src="~/scripts/jquery.signalr-2.0.2.js" type="text/javascript"></script>
<script src="~/signalr/hubs"></script>
Signalr.hubs is the main reference which gives the javascripts proxy files. If you are facing any errors please let me know.
Next thing is the property name referred in the model object creation.
this.hub.client.getAllProducts = function (allProducts) {
var mappedProducts = $.map(allProducts, function (item) {
return new productViewModel(item.productId, item.name)
});
products(mappedProducts);
}
I have updated the property names to pascal case and worked for me.
return new productViewModel(item.ProductId, item.Name)
Upvotes: 3