C# 购物车逻辑(?)与KnockoutJS的问题 目标
制作产品的动态列表 情景 我有一个购物应用程序。当我点击产品的C# 购物车逻辑(?)与KnockoutJS的问题 目标,c#,javascript,asp.net-mvc-4,razor,knockout.js,C#,Javascript,Asp.net Mvc 4,Razor,Knockout.js,制作产品的动态列表 情景 我有一个购物应用程序。当我点击产品的添加按钮时,我想在侧栏中显示我添加的产品 总结问题(您只需阅读此内容) 我的产品中有以下代码mmary/Index.cshtml(使用Razor引擎): 如您所见,有一个if检查ProductsSummary会话是否存在。如果是,则应用程序会在屏幕上显示我在摘要中添加的产品列表 如您所见,如果会话为空,应用程序将在li中显示消息,其中为空 要点是:我真的需要在[…]之后使用“模板”来显示添加到摘要中的项目吗 我的意思是,我知道当我点击
添加按钮时,我想在侧栏中显示我添加的产品
总结问题(您只需阅读此内容)
我的产品中有以下代码mmary/Index.cshtml
(使用Razor引擎):
如您所见,有一个if
检查ProductsSummary
会话是否存在。如果是,则应用程序会在屏幕上显示我在摘要中添加的产品列表
如您所见,如果会话为空,应用程序将在li
中显示消息,其中为空
要点是:我真的需要在[…]之后使用“模板”来显示添加到摘要中的项目吗
我的意思是,我知道当我点击“添加产品”按钮时,无论是否有会话,Knockout都需要显示一些内容,但是我重复相同的模板以达到类似的目的
看看这个片段:
<li data-product-id="@product.id">
<div class="product-summary-actions float-right">
<button class="btn btn-danger btn-mini remove-item">
<i class="icon-remove"></i>
</button>
</div>
<div class="product-summary-quantity">
<h6>
@product.quantity
@product.measure@(@product.quantity == 1 ? "" : "s")
</h6>
</div>
<div class="product-summary-description">
<p>@product.name</p>
</div>
</li>
正如您所看到的,这两个片段是相似的——一个表示来自数据库的数据,另一个分别表示在没有会话时使用Knockout的模型——我需要一种方法来“模板化”这一点
我真正需要的
有人进入我的网站/应用程序李>
在我的版面右侧有一个侧边栏,上面有一条消息:“摘要为空。”李>
“哦,多好的产品!我将把它添加到我的摘要中!”,然后用户单击add
按钮,“摘要为空。”消息消失,用户添加的产品以列表中项目的格式显示(与我在[第一个/第二个片段]之前传递的模板相同)
“好的,我现在将转到另一个产品类别。”——*用户单击“电视”类别*——“哦,天哪!看看这台电视!我现在将添加到我的摘要中!”——*用户单击随机电视的“添加按钮”。——列表中已经有一个产品,但另一个(电视)出现了
“哦,没关系。我没有钱。我将从我的摘要中删除这些项目。”——*用户单击摘要中每个产品的“删除按钮”*-没有产品,摘要显示:“摘要是空的。”就像魔术一样,没有任何刷新或类似的内容
(好笑,嗯?)
KnockoutJS脚本
到底发生了什么?
我正在做的工作有效果也没有效果。从技术上讲,我的代码是有效的,但我不想重复它。可能吗
技术细节
服务器端团队使用带有MVC 4和Razor引擎的C#.NET,客户端团队使用KnockoutJS和jQuery。对于空购物车消息,您可以执行以下操作:
<li class="is-empty" data-bind="visible: products().length < 1">
<p>Your summary is empty.</p>
</li>
你的摘要是空的
对于其余部分,您应该能够做到这一点(无MVC循环):
并在客户端填充列表,即使您已将项目保存到会话中。在您看来,将现有数据序列化为JSON对象,并将其保存到页面上的javascript变量中,该变量可以在文档就绪时读取,并推送到可观察的产品中
var existingItems = @Html.Raw(Json.Encode((List<MyApp.Models.Data.getSpecificProductToShoppingList_Result>)Session["ProductsSummary"]));
$(document).ready(function() {
// push existingItems into products observable.
});
var existingItems=@Html.Raw(Json.Encode((List)Session[“ProductsSummary”]);
$(文档).ready(函数(){
//将现有项目推送到可观察的产品中。
});
注意:我的语法在JSON编码上可能不太正确。您可以尝试knockoutjs模板绑定并将重复的内容放在一个文本/html脚本块中。。。如果没有其他事情的话,我很喜欢阅读你问题的背景你好,@JasonP!朋友,我们快到了!你的代码工作“完美”!但是,不幸的是,当我刷新页面时,会话的结果并不存在=(好的,所以我们需要进行一些调试。您是否确保当页面第二次加载时,产品确实在会话中?如果是,您是否查看了页面的源代码以确保existingItems对象是正确的?您的javascript控制台中是否有任何错误?您是对的,existingItems未填充-其值为null
。您说:“注意,我的语法在JSON编码上可能不太正确。”-但我不明白:语法是正确的!你确保产品列表当时确实在会话中吗?Jason,我已经解决了这个问题。你可以找到正确的语法。问题是:我的KnockoutJS脚本在summary.js
上,而这个文件没有访问@Html.Raw
语法。你知道吗?
<li data-bind="attr: { 'data-product-id': id }">
<div class="product-summary-actions float-right">
<button class="btn btn-danger btn-mini">
<i class="icon-remove"></i>
</button>
</div>
<div class="product-summary-quantity">
<h6 data-bind="text: infoComposition"></h6>
</div>
<div class="product-summary-description">
<p data-bind="text: name"></p>
</div>
</li>
$(document).ready(function () {
function Product(id, name, measure, quantity) {
this.id = ko.observable(id);
this.name = ko.observable(name);
this.measure = ko.computed(function () {
return quantity > 1 ? measure + "s" : measure;
}, this);
this.quantity = ko.observable(quantity);
this.infoComposition = ko.computed(function () {
return this.quantity() + " " + this.measure()
}, this);
}
function SummaryViewModel() {
this.products = ko.observableArray([]);
this.addToSummary = function (formElement) {
var $productId = $(formElement).children("[name=productId]").val();
var match = $(".summary")
.find("li[data-product-id=" + $productId + "]").length;
if (!match) {
var $productName =
$(formElement).children("[name=productName]").val(),
$productMeasure =
$(formElement).children("[name=productMeasure]").val(),
$productQuantity =
$(formElement).children("[name=productQuantity]").val();
this.products.push
(new Product
($productId,
$productName,
$productMeasure,
$productQuantity));
$.ajax({
type: "POST",
url: "/ProductsSummary/Add",
data:
{
productId: $productId,
productQuantity: $productQuantity
}
});
}
}
};
var summaryViewModel = new SummaryViewModel();
ko.applyBindings(summaryViewModel);
$("body").on("click", ".remove-item", function () {
summaryViewModel.products.remove(ko.dataFor(this));
$.ajax({
type: "POST",
url: "/ProductsSummary/Remove",
data: { productId: $(this).closest("li").data("product-id") }
});
});
});
<li class="is-empty" data-bind="visible: products().length < 1">
<p>Your summary is empty.</p>
</li>
<!-- ko foreach: products -->
<li data-bind="attr: { 'data-product-id': id }">
<div class="product-summary-actions float-right">
<button class="btn btn-danger btn-mini remove-item">
<i class="icon-remove"></i>
</button>
</div>
<div class="product-summary-quantity">
<h6 data-bind="text: infoComposition"></h6>
</div>
<div class="product-summary-description">
<p data-bind="text: name"></p>
</div>
</li>
<!-- /ko -->
var existingItems = @Html.Raw(Json.Encode((List<MyApp.Models.Data.getSpecificProductToShoppingList_Result>)Session["ProductsSummary"]));
$(document).ready(function() {
// push existingItems into products observable.
});