0

jsFiddle: http: //jsfiddle.net/brandondurham/g3exx/

ショッピングカートのセットアップに取り組んでおり、モデルで次のJSONデータを使用しています。

{
    "cartItems" : [
        {
            "itemName" : "Product 1",
            "itemDesc" : "One year subscription through 14 November 2013",
            "itemType" : "subscription",
            "itemPrice" : 299,
            "itemFreebies" : false
        }, {
            "itemName" : "Product 2",
            "itemDesc" : "OpenType format",
            "itemType" : "desktop",
            "itemPrice" : 4499,
            "itemFreebies" : [{
                "freebieName" : "Product 2-a",
                "freebieDesc" : "included with your workstation license",
                "freebieOriginalPrice" : 99
            }]
        }, {
            "itemName" : "Product 3",
            "itemDesc" : "OpenType format",
            "itemType" : "desktop",
            "itemPrice" : 8999,
            "itemFreebies" : [{
                "freebieName" : "Product 3-a",
                "freebieDesc" : "included with your workstation license",
                "freebieOriginalPrice" : 99
            }]
        }, {
            "itemName" : "Product 4",
            "itemDesc" : "OpenType format",
            "itemType" : "desktop",
            "itemPrice" : 99,
            "itemFreebies" : [{
                "freebieName" : "Product 4-a",
                "freebieDesc" : "included with your workstation license",
                "freebieOriginalPrice" : 99
            }]
        }, {
            "itemName" : "Product 5",
            "itemDesc" : "",
            "itemType" : "webfont",
            "itemPrice" : 49,
            "itemFreebies" : false
        }, {
            "itemName" : "Product 6",
            "itemDesc" : "for use with Cloud.typography",
            "itemType" : "webfont",
            "itemPrice" : 99,
            "itemFreebies" : false
        }
    ]
}

カート内のいくつかのタイプのアイテムの間にはいくつかの関係があります。たとえば、このJSONの最初の項目はitemType「サブスクリプション」です。ユーザーがカートにサブスクリプションを持っている場合、カートに他に何があるかに応じて、いくつかの無料のものを取得します(したがって、itemFreebies一部のアイテムにはネストされた配列があります)。また、このサブスクリプションに関連する特定の種類のアイテム(つまり、「Webフォント」)を追加することもできます。そのため、ユーザーがサブスクリプションをカートから削除する場合、これらの無料アイテムとWebフォントもすべて削除する必要があります。これを行うために現在使用している関数は次のとおりです。

removeRelatives: function (itemType) {
    var siblings = CartModel.cartItems();
    switch (itemType) {
        case "subscription":
            CartModel.cartItems.remove(function(item) { return item.itemType() == "webfont" });
            $.each(CartModel.cartItems(), function(index, sib) {
                if (sib.itemFreebies) {
                    sib.itemFreebies.removeAll();
                }
            });
        break;
    }
}

この行は、「webfont」`itemTypeに一致するルートレベルのアイテムをすべて削除します。

CartModel.cartItems.remove(function(item) { return item.itemType() == "webfont" });

そして、この2番目のビットはすべてを循環し、 falseではないノードをcartItems検索して削除します。itemFreebies

$.each(CartModel.cartItems(), function(index, sib) {
    if (sib.itemFreebies) {
        sib.itemFreebies.removeAll();
    }
});

よくわからないのは、この2番目のビットです。それは機能していますが、それを実行するための最もクリーンな方法ではないと思います。さらに、beforeRemoveネストされたもののために配置したアニメーションが機能しitemFreebiesていません。削除すると、画面から消えます。

これがHTML側です。

<ul id="cart-contents" data-bind="template: { name: 'cart-item-template', foreach: cartItems, beforeRemove: CartPackage.beforeRemove }">
    </ul>
<div id="running-totals">
    <div class="totals" data-bind="visible: cartItems().length > 0">
        <div><strong>Subtotal</strong></div>
        <div><span class="denomination">USD</span>  <strong id="subtotal"><span data-bind="formatUSD: CartPackage.totalSurcharge()"></span></strong></div>
    </div>
    <div class="empty-cart">There are currently no items in your shopping cart.</div>
</div>
<div class="call-to-action" data-bind="visible: cartItems().length > 0">
    <div class="split">
        <div class="messages">&nbsp;</div>
        <div class="actions">
            <button class="cancel">Continue Shopping</button>
            <button class="action">Checkout</button>
        </div>
    </div>
</div>
<input type="hidden" value="" data-bind="value: cartItems().length">
<script type="text/html" id="cart-item-template">
    <li>
        <button class="delete-item">Delete</button>
        <ul>
            <li data-bind="attr: {'class': itemType}">
                <div class="details">
                    <h5><strong data-bind="text: itemName">Product Name</strong><!-- ko if: itemType() === 'desktop' --> Desktop fonts<!-- /ko --><!-- ko if: itemType() === 'webfont' --> Webfonts<!-- /ko --></h5>
                    <p data-bind="text: itemDesc">One year subscription through 14 November 2013</p>
                </div>
                <div class="quantity">
                    <!-- ko if: itemType() === "subscription" --><select data-bind='options: SubscriptionData, optionsText: "name", optionsValue: "price", value: itemPrice'></select><!-- /ko -->
                    <!-- ko if: itemType() === "desktop" || itemType() === "webfont" --><select data-bind='options: DesktopData, optionsText: "name", optionsValue: "price", value: itemPrice'></select><!-- /ko -->
                </div>
                <div class="cost" data-bind="formatUSD: itemPrice">$ 0</div>
            </li>
            <!-- ko if: itemFreebies -->
            <!-- ko foreach: itemFreebies, beforeRemove: CartPackage.beforeRemove -->
            <li class="webfont">
                <div class="details">
                    <h5><strong data-bind="text: freebieName">Product</strong> Webfonts</h5>
                    <p data-bind="text: freebieDesc">Included with your workstation license</p>
                </div>
                <div class="quantity">&nbsp;</div>
                <div class="cost">
                    <span class="original-price" data-bind="formatUSD: freebieOriginalPrice">$ 49.00</span>  <span class="free">FREE!</span>
                </div>
            </li>
            <!-- /ko -->
            <!-- /ko -->
        </ul>
    </li>
</script>

私が機能していない理由についての提案beforeRemoveはありますか?私がやろうとしていることを達成するためのよりクリーンな方法は?

ありがとう!さらにコードを表示する必要がある場合はお知らせください...

4

1 に答える 1

1

アニメーションについては、beforeRemove上記のコメントにリストした構文の問題のようです。

私が今言えることから、適切に機能しているようです:http: //jsfiddle.net/rniemeyer/g3exx/3/

景品を削除するコードについては、次のように簡略化できます。

$.each(CartModel.cartItems(), function(index, sib) {
    sib.itemFreebies([]);
});

リレーションシップピースについては、現在行っていることよりも優れたモデルを作成する簡単な方法はないと思います。1つの考えは、ルートビューモデル上に、のような全体的な概念を表す計算されたオブザーバブルを作成することhasSubscriptionです。次に、その値が変更された場合、各カートアイテムはhasSubscription、独自の景品をサブスクライブして削除できます。少なくとも、サブスクリプションカートアイテムと他のカートアイテムの間に間接参照が追加されます。ただし、アイテムをマップする方法が複雑になります。

このようなオプションを追求したい場合は、さらにサポートさせていただきます。

于 2012-08-25T01:51:10.967 に答える