我使用ASP.NET将REST请求发送到我无法控制的服务器。一种类型的请求是针对特定产品。该产品可以有许多不同的版本。一些变化可能是尺寸,颜色,金属(金,银等)。在一些产品的情况下,可能有一年变化和一个制造(福特,道奇等)。这里的要点是变化很多,有时只有一个变化,而其他时候产品可能有3或4个变化。
此外,还没有设置变体可能包含的选择项的列表。例如,一种产品可能有粉红色,绿色,蓝色的颜色变化,而另一种产品可能只有黑色或白色。尺码有时可以包含8,10,12和14个珠宝物品,或者小号,中号,大号可以包含一件衣物。
产品的变体组合始终在REST响应中返回。例如,我总是会知道产品变体属性,例如“颜色”,“尺寸”等等。我发现提供这些变体选项的最简洁方法是通过使用DropDownLists。我可以动态创建一个DropDownList' Color'并用粉红色,绿色和红色的选项填充它 - 或者其他任何东西。
粉红色和小号的产品与粉红色和大号的产品ID不同。
因此,如果网络访问者查找产品然后选择所需的变体,我需要客户端脚本逻辑,它将关联产品ID(基于所选的变体),以便将产品添加到他的购物车中。
REST响应包含一系列与变体组合相关联的产品ID。
我很抱歉这么冗长的解释,但我现在还没有任何代码可以提供。
我想知道的是,由于JavaScript不支持多维数组,因此我必须使用哪些选项来使用客户端Javascript逻辑来根据所选的值确定产品ID或者更多DropDownLists?
服务器端,无论是在我的XSLT模板中还是在ASP.NET代码隐藏中,我都可以使用" Page.ClientScript.RegisterArrayDeclaration"以某种方式,但我真的需要一些对特定变体名称无知的逻辑。
所以,例如,我有一个名为" WIDGET"并且它具有以下变体(布置为ProductID,variation1,variation2):
"00001", "Black", "Small"
"00002", "Pink", "Small"
"00003", "Red", "Small"
"00004", "Black", "Medium"
"00005", "Pink", "Medium"
"00006", "Red", "Medium"
"00007", "Black", "Large"
"00008", "Pink", "Large"
"00009", "Red", "Large"
我有2个DropDownLists:
颜色:黑色,粉红色,红色
和
尺寸:小,中,大
如何根据所选的variation1和variation2的值确定ProductID?请记住,这些属性是动态创建/填充的。客户端Javascript需要是通用的。我可能需要为Javascript逻辑创建几个数组。
通过可能的变化:
Page.ClientScript.RegisterArrayDeclaration("product_variation", "Color")
Page.ClientScript.RegisterArrayDeclaration("product_variation", "Size")
另外,如上所述,包含ProductID及其相关变体:
Page.ClientScript.RegisterArrayDeclaration("product_1_ID", "00001")
Page.ClientScript.RegisterArrayDeclaration("product_1_Color", "Black")
Page.ClientScript.RegisterArrayDeclaration("product_1_Size", "Small")
Page.ClientScript.RegisterArrayDeclaration("product_2_ID", "00002")
Page.ClientScript.RegisterArrayDeclaration("product_2_Color", "Black")
Page.ClientScript.RegisterArrayDeclaration("product_2_Size", "Medium")
等。但说实话,我不知道Javascript,我只是不知道如何在不看示例的情况下解决这个问题。我已经搜索过,但是找不到任何东西。我还可以在asp页面中创建一些隐藏的输入,如果它有助于客户端脚本。
有人能指出一个例子来帮我解决这个问题吗?是否有更简单/更合适的方式来做我需要的事情?
感谢您阅读所有这些内容。我几乎没有发布它,因为它太长了......
修改
以下gilly3提交的想法是正确的,我认为这应该如何运作。同样,我对任何风格的Javascript都有非常有限的经验,但是我尽可能地遵循了说明。我在某个地方遇到了问题,所以我想显示我的进度并询问你是否看错了。
在Product.aspx中,我创建了一个隐藏字段,其中包含正在查看的产品的变体:
<input id="hfdatalist" type="hidden" value="[
{"Id": "00001","Color": "Tidal", "Size": "2"},
{"Id": "00002","Color": "Tidal", "Size": "4"},
{"Id": "00003","Color": "Tidal", "Size": "6"},
{"Id": "00004","Color": "Tidal", "Size": "8"},
{"Id": "00005","Color": "Tidal", "Size": "10"},
{"Id": "00006","Color": "Tidal", "Size": "12"},
{"Id": "00007","Color": "Tidal", "Size": "14"},
{"Id": "00008","Color": "Tidal", "Size": "16"}
]" />
包含变体属性(颜色和大小)的隐藏字段:
<input id="hfpropctlmap" type="hidden" value=
"{"ddSize": "Size", "ddColor": "Color"}"
/>
我有两个下拉列表。一个用于ID为ddSize,另一个用于ID为ddColor的Color。 ddColor(在这种情况下)只有一个选项,&#34; Tidal&#34;。 ddSize有多个选项,2,4,6,8,10,12,14和16.单击这些下拉列表中的任何一个选项都将触发以下Javascript。
在Product.aspx中,我包含了gilly3提供的Javascript示例。我对一些代码的放置做了一些假设,但在大多数情况下我已经逐字地使用了它:
<!-- Augment JS files -->
<script type="text/JavaScript" src="../Scripts/augment.min.js"></script>
<!-- Variations Support Script -->
<script type="text/JavaScript">
$("select").change(function () {
var data = $.parseJSON($("#[id*='hfdatalist']").val());
var propertyControlMap = $.parseJSON($("#[id*='hfpropctlmap']").val());
var filteredData = data;
var selections = $("select").map(function () {
return {
Property: propertyControlMap[this.id],
Value: $(this).val()
};
}).get();
filteredData = data.filter(function (item) {
return selections.every(function (selection) {
return item[selection.Property] == selection.Value;
});
});
var selectedId = filteredData.length == 1 ? filteredData[0].Id : "";
$("#[id*='SelectedVariationASIN']").val(selectedId)
});
</script>
我知道这个代码有点乱,因为我有一些调试帮助。有2个警报显示保存到变量test和test1的隐藏字段的内容。这两个都完美地显示了隐藏字段的值(我想!)。
我设置断点并查看数据变量的内容。数组有8个元素(0-7),每个元素都包含正确的Id,Color和Size值。属性名称正确显示,实际数据有效。
与propertyControlMap相同。当我查看其数据时,属性名称和值是正确的。有2个元素(0-1)。
当然,filteredData也是正确的,因为此时它只是数据var的副本。
我看下一个var是选择。这是第一个迹象表明事情并不恰当。分配选择并查看其值后,我可以看到有9种方法和2种元素(0-1)。在查看元素时,选择[0] .Property是未定义的&#39;它的价值不正确&#39; 1036682&#39;。我认识到存储在名为&#34; hfSearchIndex&#34;的页面上另一个隐藏字段中的值的值。我不知道为什么会这样。该字段根本没有在脚本中引用。它与我的程序逻辑的这一部分无关。
奇怪的是,选择[1] .Property也包含&#39; undefined&#39;尽管Value包含我在ddSize下拉列表中点击的任何尺寸的实际值。所以,它是部分正确的。
从这一点来看,代码是不可预测的,可能不值得评论,除非说最后一行代码selectedId返回&#39;&#39;。
编辑#2
gilly3提到propertyControlMap可能不包含下拉列表控件的正确ID。我不是肯定的,但我认为它确实包含正确的ID。但是,有一个Master Page,还有一个asp:PlaceHolder控件。所以Name属性确实会有一些错误。
以下是一些事实:
var selections =
。执行此行代码后,selections
不包含有效数据。而不是选择等于:ID = 00001,颜色=黑色,大小=小它等于undefined = 1036682,颜色=黑色,大小=小。出于某种原因,ProductID未正确设置。在呈现页面之后,我查看了源代码,这里是下拉列表:
<select name="ctl00$PageContent$ddSize" id="ddSize">
<option value="Small">Small</option>
<option value="Medium">Medium</option>
</select>
<select name="ctl00$PageContent$ddColor" id="ddColor">
<option value="Black">Black</option>
<option value="Cobalt">Cobalt</option>
<option value="Coral">Coral</option>
<option value="Jade">Jade</option>
<option value="Yellow">Yellow</option>
</select>
在页面的下方,还有另一个隐藏字段与此问题/答案中讨论的逻辑完全无关:
<input type="hidden" name="SearchIndex" value="1036682">
我无法弄清楚为什么在var selections
我不确定如何进一步记录我的问题。我怀疑,就像gilly3一样,虽然propertyControlMap在其所有元素/属性中都包含完全有效/正确的数据,但我引用控件ID的方式有些不正确。
如果由于Master Page和PlaceHolder导致控件ID出现问题,我该如何解决这个问题?
注意:使用XSLT在XSLT转换中创建下拉列表控件在收到的REST响应上运行样式表。使用反序列化的REST响应在页面代码隐藏中创建隐藏字段。
感谢您帮助我了解这个gilly3。由于我不了解Javascript,我真的陷入了困境。在这种情况下,我必须使用Javascript与跨浏览器兼容。让我有点紧张,在我的项目中包含我真的不太了解的代码,但我会特别注意它。
希望我不要混淆。 :S
答案 0 :(得分:1)
将数据作为对象数组存储在JavaScript中。如果您有List<T>
强类型对象,则可以使用new JavaScriptSerializer().Serialize(myList);
将其序列化为JSON。但是,听起来您手动解析XML,因此您可能还需要手动创建JSON。无论如何,你最终会得到一个格式如下的字符串:
[{
"Id": "00001",
"Color": "Black",
"Size": "Small"
},
{
"Id": "00002",
"Color": "Pink",
"Size": "Small"
},
...
{
"Id": "00009",
"Color": "Red",
"Size": "Large"
}]
您需要一种方法将对象属性名称映射到相应的下拉列表。我会用JSON表达它:
{
"<Color DropDownList.ClientID Goes Here>": "Color",
"<Size DropDownList.ClientID Goes Here>": "Size",
... // etc
}
将这些JSON字符串删除到页面上的隐藏字段中。在JavaScript中,您将使用以下内容对其进行反序列化:
var data = $.parseJSON($("#<%= DataList.ClientID %>").val());
var propertyControlMap = $.parseJSON($("#<%= PropCtrlMap.ClientID %>").val());
var filteredData = data;
然后将onchange
处理程序附加到下拉列表中,以便在选择更改时过滤数据。您需要创建一个属性名称数组和当前选定的值来测试您的数据。然后,您可以使用Array.filter()
将数据减少到满足函数指定条件的项目。您可以在过滤器功能中使用Array.every()
来测试每个项目,看它是否与所有选项匹配。 编辑然后将所选项目的ID填入隐藏字段,以便您可以通过按钮的点击处理程序在服务器上访问它:
$("select").change(function () {
var selections = $("select").map(function () {
return {
Property: propertyControlMap[this.id],
Value: $(this).val()
};
}).get();
filteredData = data.filter(function(item) {
return selections.every(function(selection) {
return item[selection.Property] == selection.Value;
});
});
var selectedId = filteredData.length == 1 ? filteredData[0].Id : "";
$("#<%= SelectedItemId.ClientID %>").val(selectedId)
});
如果您想支持IE8或更早版本,请务必添加对Array.filter()
和Array.every()
的支持,因为在IE9之前不支持这些内容。
编辑:如何访问服务器上的ID:
void AddToCartButton_Click(object sender, EventArgs e)
{
ShoppingCart.AddToCart(SelectedItemId.Value);
}
但是,如果没有JavaScript,你也不能这样做吗?您可以使用所选值在单击处理程序中过滤服务器上的项目。下面是一个简化 - 你需要迭代下拉列表,而不是硬编码 - 但它说明了我的思路。
void AddToCartButton_Click(object sender, EventArgs e)
{
string itemsXml = RestUtility.RequestItems();
XDocument xItemsDoc = new XDocument(itemsXml);
IEnumerable<XElement> xItems = xItemsDoc.Descendants("Item");
XElement xSelected = xItems.SingleOrDefault(e =>
e.Attribute("Color").Value == ColorSelector.SelectedValue &&
e.Attribute("Size").Value == SizeSelector.SelectedValue);
if (xSelected != null)
{
ShoppingCart.AddToCart(xSelected.Attribute("Id").Value);
}
}