0

ASP.NETを使用して、制御できないサーバーにREST要求を送信しています。リクエストの1つのタイプは、特定の製品に対するものです。製品は多くの異なるバリエーションで利用できる場合があります。バリエーションには、サイズ、色、金属(金、銀など)があります。一部の製品の場合、年のバリエーションとメーカー(フォード、ダッジなど)が存在する可能性があります。ここでのポイントは、バリエーションが多く、バリエーションが1つしかない場合もあれば、製品に3つまたは4つのバリエーションがある場合もあるということです。

また、バリエーションに含まれる可能性のある選択の数のセットリストはありません。たとえば、ある製品はピンク、グリーン、ブルーのカラーバリエーションで利用できる場合がありますが、別の製品はブラックまたはホワイトでのみ利用できる場合があります。サイズには、ジュエリーアイテムの場合は8、10、12、14が含まれる場合があり、衣料品の場合は小、中、大が含まれる場合があります。

製品のバリエーションの組み合わせは、常にREST応答で返されます。たとえば、「色」、「サイズ」などの商品バリエーション属性は常に知っています。これらのバリエーションオプションを表示する最もクリーンな方法は、DropDownListsを使用することです。'Color'のDropDownListを動的に作成し、ピンク、緑、赤などのオプションを入力できます。

ピンクの色とサイズが小さい商品は、ピンクと大きい商品IDとは商品IDが異なります。

したがって、Web訪問者が製品を検索し、目的のバリエーションを選択する場合、製品をショッピングカートに追加できるように、(選択したバリエーションに基づいて)製品IDを関連付けるクライアント側のスクリプトロジックが必要です。

REST応答には、バリエーションの組み合わせに関連付けられた製品IDの配列が含まれています。

説明が長すぎて申し訳ありませんが、現時点で提示するコードはありません。

私が知りたいのは、JavaScriptは多次元配列をサポートしていないため、1つ以上のDropDownListsの選択された値に基づいて製品IDを決定するために、クライアント側のJavascriptロジックを使用する必要があるオプションは何ですか?

サーバー側の1つで、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を持っています:

カラー:ブラック、ピンク、レッド

サイズ:小、中、大

選択したバリエーション1とバリエーション2の値に基づいてProductIDを決定するにはどうすればよいですか?これらの属性は動的に作成/入力されることに注意してください。クライアントのJavascriptは汎用である必要があります。おそらく、Javascriptロジック用にいくつかの配列を作成する必要があります。

可能なバリエーションを渡すための1つ:

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"}"
/>

ドロップダウンリストが2つあります。1つはIDがddSizeのSize用で、もう1つはIDがddColorのColor用です。ddColor(この場合)には、「Tidal」という1つのオプションしかありません。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>

デバッグ支援が含まれているので、このコードは少し厄介だと思います。変数testおよびtest1に保存された非表示フィールドの内容を表示する2つのアラートがあります。これらは両方とも、非表示フィールドの値を完全に表示します(私は思います!)。

ブレークポイントを設定し、データ変数の内容を表示します。配列には8つの要素(0〜7)があり、それぞれに正しいId、Color、およびSizeの値が含まれています。プロパティ名は正しく表示され、実際のデータは有効です。

propertyControlMapと同じです。そのデータを表示すると、プロパティの名前と値は正しいです。2つの要素(0-1)があります。

もちろん、この時点ではデータ変数の単なるコピーであるため、filteredDataも正しいです。

私が見る次の変数は選択です。これは、何かが正しくないことを示す最初の兆候です。選択範囲が割り当てられ、その値を表示すると、9つのメソッドと2つの要素(0-1)があることがわかります。要素を見ると、selections [0] .Propertyは「未定義」であり、その値は「1036682」ではありません。「hfSearchIndex」というページの別の非表示フィールドに格納されている値から値を認識します。なぜこれが起こるのか私にはわかりません。このフィールドは、スクリプトではまったく参照されていません。それは私のプログラムロジックのこの部分とは何の関係もありません。

奇妙なことに、selections [1].Propertyには'undefined'も含まれていますが、ValueにはddSizeドロップダウンリストでクリックしたサイズの実際の値が含まれています。だから、それは部分的に正しいです。

この時点から、コードは予測不可能であり、コードの最後の行であるselectedIdが''を返すことを除いて、おそらくコメントする価値はありません。

gilly3または他の誰か、私が間違ったことを見ることができますか?

編集#2

gilly3は、propertyControlMapにドロップダウンリストコントロールの正しいIDが含まれていない可能性があると述べました。私は前向きではありませんが、正しいIDが含まれていると思います。ただし、関連するマスターページとasp:PlaceHolderコントロールもあります。そのため、Name属性にはいくつかのマングリングが発生しています。

ここにいくつかの事実があります:

  1. hfdatalistは完璧に見えます(上に表示されているように)。
  2. hfpropctlmapは完璧に見えます(上に表示されているように)。
  3. varデータは正しく初期化されます。配列の各要素には、hfdatalistの非表示フィールドで指定されている完全なID、色、およびサイズの値が含まれています。(例:00001、黒、小)。
  4. varpropertyControlMapは正しく初期化されます。配列の各要素には、ドロップダウンリストの完全なIDと正しいバリエーション名が含まれています。(例:ddColorとColor)。
  5. 問題の最初の兆候はvar selections =、Javascriptにあります。このコード行が実行された後、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">

このフィールドの値( "1036682")がのProductID値で使用されている理由がわかりませんvar selections

問題をこれ以上文書化する方法がわかりません。propertyControlMapには、そのすべての要素/プロパティに完全に有効で正しいデータが含まれていますが、gilly3のように、コントロールIDの参照方法に誤りがあるのではないかと思います。

これがマスターページとPlaceHolderによるコントロールIDの問題である場合、これを回避するにはどうすればよいですか?

注:ドロップダウンリストコントロールは、受信したREST応答で実行されたXSLTスタイルシートを使用してXSLT変換で作成されます。非表示フィールドは、逆シリアル化されたREST応答を使用してページコードビハインドに作成されます。

このgilly3で私を助けてくれてありがとう。私はJavascriptを知らないために本当に行き詰まっています。この状況でクロスブラウザ互換にするために、Javascriptを使用する必要があります。あまりよく知らないコードをプロジェクトに含めるのは少し緊張しますが、特に注意を払います。

私が混乱していないことを願っています。:S

4

1 に答える 1

1

データをオブジェクトの配列としてJavaScriptに保存します。強く型付けされたオブジェクトがある場合は、List<T>を使用してそれをJSONにシリアル化できます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以前をサポートする場合は、IE9より前ではネイティブにサポートされていないため、必ずとのサポートを追加してArray.filter()ください。Array.every()

編集:サーバー上の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);
    }
}
于 2012-06-07T00:43:57.277 に答える