繁体   English   中英

动态创建DropDownList值作为Javascript数组的键

[英]Dynamically created DropDownList values as Key for Javascript array

我正在使用ASP.NET将REST请求发送到我无法控制的服务器。 一种请求是针对特定产品。 该产品可能有许多不同的版本。 其中一些变化可能是大小,颜色,金属(金,银等)。 对于某些产品,可能会有年份变化和品牌(福特,道奇等)。 这里的要点是,变体很多,有时只有一个变体,而其他时候一个产品可能有3或4个变体。

同样,没有设置变体可能包含多少选择的设置列表。 例如,一种产品可能以粉红色,绿色,蓝色的颜色提供,而另一种产品可能仅以黑色或白色提供。 尺寸有时会包含8、10、12和14(对于珠宝首饰而言),或者小,中,大(对于服装而言)。

产品的变体组合始终会在REST响应中返回。 例如,我将永远知道产品的变体属性,例如“颜色”,“尺寸”等。我发现,呈现这些变体选项的最简洁方法是使用DropDownLists。 我可以动态地创建一个'Color'的DropDownList并用Pink,Green和Red或其他选项填充它。

颜色为粉红色且尺寸为小号的产品具有与粉红色和大号产品不同的产品ID。

因此,如果网络访问者查找产品然后选择所需的变体,那么我需要客户端脚本逻辑,该逻辑将与产品ID相关联(基于所选变体),以便可以将产品添加到他的购物车中。

REST响应包含与变体组合相关联的产品ID数组。

冗长的解释很抱歉,但是目前我没有任何代码可以提供。

我想知道的是,由于JavaScript不支持多维数组,我必须使用哪些选项才能使用客户端Javascript逻辑基于一个或多个DropDownLists的选定值来确定产品ID?

在服务器端,无论是在我的XSLT模板中,还是在ASP.NET代码中,都可以以某种方式使用“ Page.ClientScript.RegisterArrayDeclaration”,但是我确实需要一些对具体变体名称不了解的逻辑。

因此,例如,我有一个名为“ WIDGET”的产品,它具有以下变体(布局为ProductID,variant1,variant2):

"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的Size,另一个用于ID为ddColor的Color。 ddColor(在这种情况下)只有一个选项“潮汐”。 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的隐藏字段的内容。 这两个都完美地显示了隐藏字段的值(我认为!)。

我设置一个断点并查看数据变量的内容。 数组(0-7)有8个元素,每个元素都包含正确的ID,颜色和大小值。 属性名称正确显示,并且实际数据有效。

与propertyControlMap相同。 当我查看其数据时,属性名称和值是正确的。 有2个元素(0-1)。

当然,filteredData也是正确的,因为此时它只是数据var的副本。

我要看的下一个变量是选择。 这是表明事情不太正确的第一个迹象。 分配选择并查看其值之后,可以看到有9种方法和2个元素(0-1)。 查看元素时,selections [0] .Property为“未定义”,其值不正确为“ 1036682”。 我从存储在页面上另一个隐藏字段“ hfSearchIndex”中的值中识别出该值。 我不知道为什么会这样。 脚本中完全没有引用此字段。 它与程序逻辑的这一部分无关。

奇怪的是,selections [1] .Property也包含“ undefined”,尽管Value包含我在ddSize下拉列表中单击的任何Size的实际值。 因此,这是部分正确的。

从这一点来看,代码是不可预测的,可能不值得评论,只是说代码的最后一行selectedId返回。

gilly3或其他任何人,您能看到我做错了吗?

编辑#2

gilly3提到propertyControlMap可能未包含dropdownlist控件的正确ID。 我不是很肯定,但我认为它确实包含正确的ID。 但是,涉及到一个母版页和一个asp:PlaceHolder控件。 因此,Name属性确实进行了一些修改。

以下是一些事实:

  1. hfdatalist看起来很完美(如上所示)。
  2. hfpropctlmap看起来很完美(如上所示)。
  3. var数据已正确初始化。 数组的每个元素都包含hfdatalist隐藏字段中指定的完美ID,颜色和大小值。 (即:00001,黑色,小)。
  4. var propertyControlMap已正确初始化。 数组的每个元素都包含下拉列表的完美ID和正确的变体名称。 (即:ddColor和Color)。
  5. 问题的第一个迹象是在Javascript中的var selections = 执行此行代码后, selections不包含有效数据。 代替等于:ID = 00001,Color = Black,Size = Small的选择,它等于undefined = 1036682,Color = Black,Size = Small。 由于某些原因,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的ProductID值中使用了此字段的值(“ 1036682”)

我不确定如何进一步记录我的问题。 我确实像gilly3一样怀疑我引用控件ID的方式有问题,尽管propertyControlMap的所有元素/属性中确实包含完全有效/正确的数据。

如果由于母版页和PlaceHolder而导致控件ID出现问题,我该如何解决?

注意:使用在收到的REST响应上运行的XSLT样式表在XSLT转换中创建下拉列表控件。 使用反序列化的REST响应在页面代码背后创建隐藏字段。

谢谢您对我的帮助。 由于缺乏对Java语言的了解,我真的陷入了困境。 在这种情况下,我必须使用Javascript才能跨浏览器兼容。 在我确实不了解的项目中包含代码让我有些紧张,但是我会特别注意它。

希望我不要感到困惑。 :S

将数据作为对象数组存储在JavaScript中。 如果您具有强类型对象的List<T> ,则可以使用new JavaScriptSerializer().Serialize(myList); 但是,听起来好像您是在手动解析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);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM