2012-08-24 53 views
0

的jsfiddlehttp://jsfiddle.net/brandondurham/g3exx/在Knockout.js有條件去除根級和嵌套observableArrays

我工作的一個購物車的設置,並在我的模型使用以下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數組)。他們也被允許添加與此訂閱相關的某些類型的項目(即「webfonts」)。因此,當用戶從他們的購物車中移除訂閱時,所有這些免費項目和網頁字體也必須被移除。這是我目前正在使用要做到這一點的功能:

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; 
    } 
} 

這條線將刪除匹配「web字體」`ITEMTYPE任何根級別的項目:通過所有cartItems

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

而且這第二位週期而對於itemFreebies節點,這不是假的,並刪除它的搜索:

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

這是在這裏,我不知道這第二位。它工作正常,但我懷疑這不是最簡單的方法。另外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不工作?更清潔的方式來實現我想要做的事情?

謝謝!讓我知道如果你需要看到更多的代碼...

+0

對於你的'beforeMove'語法,你需要像'ko foreach:{data:itemFreebies,beforeRemove:CartPackage.beforeRemove}'這樣做,否則它只是一個'beforeRemove'頂層綁定,除非它們被忽略是使用該名稱的自定義綁定。 –

回答

1

對於beforeRemove動畫,它看起來像只是我在上面的評論中列出的語法問題。

好像是從我現在可以告訴恰當地工作:http://jsfiddle.net/rniemeyer/g3exx/3/

對於去除贈品的代碼,你可以把它簡化爲:

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

對於關係塊,我不我認爲有一種簡單的方法可以比現在做的更好地建模它。一個想法是在您的根視圖模型上創建代表任何整體概念的計算觀察值,如hasSubscription。然後,每個購物車項目可以訂閱hasSubscription並刪除自己的贈品,如果價值改變。它至少會在預訂購物車項目和其他購物車項目之間添加一些間接性。但是,這會增加您必須映射項目的複雜性。

如果您想追求類似此選項的功能,我會很樂意進一步提供幫助。

+0

謝謝!任何想法爲什麼動畫在刪除時不在免費贈品上工作? –

+0

看起來好像免費贈品在慢下來時在小提琴中動畫。你是否期待不同的效果? –