2016-11-22 11 views
3

電子商取引タイプのアプリのチェックアウトページを作成しようとしています。チェックアウトには、価格、数量のデータベースから来るOrderItemのリストがあります。これらを選択して組み合わせることができます。さらに、私はあなたのバスケットに "アドオン"のリストを別の場所にレンダリングする必要があります。これはOrderItems(同じプロパティー)ですが、タイプが異なります。2つのコンポーネントの要素を組み合わせて表示する

私はあなたが選ぶことができるOrderItemの配列をレンダリングするためのVue.jsコンポーネントを持っています。私はこの方法で同じコンポーネントを2回レンダリングしています。しかし、「選択された」プロパティは、モデルを一方のリストまたは他方のリストを形成するが、両方から同時には成立しない。私は両方のリストから項目(シンプルORDERITEMSおよびアドオン)を保持するために選択された小道具をしたいと思い

フィドル:https://jsfiddle.net/w8vfb64L/

コード:

テンプレート:

<section class="content"> 
    <div class="row" id="app"> 
    <div class="col-md-8"> 
     <div class="box box-primary"> 
     <div class="box-body"> 
      <div class="row"> 
      <div class="col-md-12"> 
       <div class="form-group"> 
       <label class="control-label required">Items</label> 
       <div class="col-md-12"> 
<entries :entries="{ 0 : { shareSize : 'Small', quantity : '1', itemPrice : '24', frequency : '' }, 1 : { shareSize : 'Medium', quantity : '1', itemPrice : '35', frequency : '' }, 2 : { shareSize : 'Large', quantity : '1', itemPrice : '46', frequency : '' } }" 
        :selected="selected"></entries> 
        </div> 
        <div class="col-md-12"> 
        <label class="control-label required">Addons</label> 
        <entries :entries="{ 0 : { shareSize : 'Large', quantity : '1', itemPrice : '46', frequency : '' } }" :selected="selected"></entries> 

       </div> 
       </div> 
      </div> 
      </div> 
     </div> 
     </div> 
     <div class="col-md-4"> 
     <div class="box box-info"> 
      <div class="box-body" style="padding:15px;"> 
      <div class="container-fluid"> 
       <div class="form-group"> 
       <div class="control-label"> 
        <label>Summary</label> 
       </div> 
       <div class="form-control" v-for="item in selected"> 
        <span class="pull-left small-box-footer">{{ item.shareSize }}</span> 
        <span class="pull-right">{{ item.quantity + ' x $ ' + (item.itemPrice*item.quantity).toFixed(2)}}</span> 
       </div> 
       <div class="control-label"> 
        <label>Payment plan</label> 
       </div> 
       <div class="col-md-12"> 
        {{ '$ ' + totalAdvance.toFixed(2) }} - advance 
       </div> 
       <div class="col-md-12"> 
        {{ '$ ' + totalFirstWeek.toFixed(2) }} - first week 
       </div> 
       <div class="col-md-12"> 
        {{ '$ ' + onDeliveryPayment.toFixed(2) }}/ week on each of the {{ weeks }} weeks of the subscription 
       </div> 
       <div class="col-md-12 row"> 
        <div class="control-label"><strong><span class="pull-left">Total</span><span class="pull-right">{{ '$ ' + total.toFixed(2) }}</span></strong></div> 
       </div> 
       <div class="col-md-12 row"> 
        <div class="title"><strong><span class="pull-left">Total due now</span><span class="pull-right">{{ '$ ' + totalAdvance.toFixed(2) }}</span></strong></div> 
       </div> 
       </div> 
      </div> 
      </div> 
     </div> 
     </div> 
    </div> 
    </div> 
</section> 

<!-- component template --> 
<template id="entries"> 
    <div class="col-md-12"> 
    <div class="form-group" v-for="(entry, key) in entriesCopy" v-bind:entry="entry"> 
     <div class="form-group col-md-12"> 
     <div class="col-md-12"> 
      <div class="col-md-4"> 
      <input type="checkbox" v-bind:value="entry" v-model="selectedCopy"> 
      </div> 
      <div class="col-md-4">{{entry.shareSize}}</div> 
      <div class="col-md-4">{{'$ ' + Number(entry.itemPrice).toFixed(2) }}</div> 
     </div> 
     <div class="form-group col-md-12"> 
      <div class="col-md-6"> 
      <input type="number" v-model="entry.quantity" :value="entry.quantity" /> 
      </div> 
     </div> 

     </div> 
    </div> 
    </div> 
</template> 

Javascriptを:

var bus = new Vue(); 

var entriesComponent = Vue.component('entries', { 
    template: '#entries', 
    props: { 
    entries: [Array, Object], 
    selected: Array, 
    addons: Array, 
    frequencies: [Array, Object], 
    }, 
    created: function() { 
    this.entriesCopy = this.entries; 
    this.selectedCopy = this.selected; 
    }, 
    watch: { 
    selectedCopy: function(val, oldVal) { 
     bus.$emit('selected-changed', val); 
    } 
    }, 
    data: function() { 
    return { 
     entriesCopy: [], 
     selectedCopy: [] 
    } 
    } 
}); 

new Vue({ 
    el: '#app', 
    data: { 
    entries: [], 
    selected: [], 
    addons: [], 
    frequencies: [], 
    paymentConfig: { 
     advance: 25, 
     firstweek: 25, 
     ondelivery: 50, 
    }, 
    weeks: 12, 
    }, 
    components: { 
    'entriesComponent': entriesComponent, 
    }, 
    created: function() { 
    // store this to use with Vue.set 
    var temp = this; 
    bus.$on('selected-changed', function(selected) { 
     // vm.$set deprecated 
     Vue.set(temp, 'selected', selected); 
    }); 
    }, 
    computed: { 
    totalAdvance: function() { 
     return (this.paymentConfig.advance * this.total)/100; 
    }, 
    totalFirstWeek: { 
     get: function() { 
     return (this.paymentConfig.firstweek * this.total)/100; 
     }, 
    }, 
    onDeliveryPayment: { 
     get: function() { 
     return (this.paymentConfig.ondelivery * this.total)/(this.weeks * 100); 
     } 
    }, 
    total: { 
     get: function() { 
     var sum = 0; 
     var weeks = this.weeks; 
     this.selected.forEach(function(item) { 
      sum += weeks * item.itemPrice * item.quantity; 
     }); 
     console.log(sum); 
     return sum; 
     } 
    } 
    } 
}); 
+0

フィドル:そこで代わりにコンポーネントのVモデルを設定することにあなたが経由項目のいずれかのフィールドを更新することができる方法を渡しますアドオンと呼ばれるコンポーネントに別の変数を追加します。しかし、これは私の視点から少し冗長です。 – anegrea

+0

あなたがしていることは非常に不明です。あなたの 'OrderItems'はどこですか?どうしたの ? – Elfayer

+0

質問を編集してさらに情報を追加します。申し訳ありません@Elfayer – anegrea

答えて

2

リファクタリングをかなりしていたので、あなたがカートを作りたいと思っていた方法と密接に関係しています。しかし、それは本当にあなたがあなたのデータを構造化する方法をの観点から再考のビットを必要と:私は、製品のオブジェクトの上に1つの以上のフィールドを更新できるようにするにはhttps://jsfiddle.net/thebigsurf/w8vfb64L/11/

EDIT

ここフィドルですあなたは現在、このためにv-modelを使用できるとは思わない。私は管理現時点でhttps://jsfiddle.net/thebigsurf/0chtzwjd/2/

var entriesComponent = Vue.component('entries', { 
 

 
    template: '#entries', 
 
    
 
    props: { 
 
     item: Object, 
 
     itemKey: String, 
 
     selected: Boolean, 
 
     updateSelected: Function, 
 
     updateItem: Function, 
 
    }, 
 
    
 
    data() { 
 
    \t return { 
 
     \t quantity: 0, 
 
      message: '', 
 
     } 
 
    }, 
 
    
 
    created() { 
 
    \t this.quantity = this.item.quantity 
 
     this.message = this.item.message 
 
    }, 
 
    
 
    watch: { 
 
    \t quantity() { 
 
     \t this.updateItem(this.itemKey, 'quantity', this.quantity) 
 
     }, 
 
    \t message() { 
 
     \t this.updateItem(this.itemKey, 'message', this.message) 
 
     }, 
 
    } 
 
    
 
}); 
 

 
new Vue({ 
 

 
    el: '#app', 
 
    
 
    data: { 
 
    \t allProducts: { 
 
     \t 'foo': { shareSize: 'Small', quantity: '1', itemPrice: '24', message: '' }, 
 
      'bar': { shareSize: 'Medium', quantity: '1', itemPrice: '35', message: '' }, 
 
      'baz': { shareSize: 'Large', quantity: '1', itemPrice: '46', message: 'hello' }, 
 
     \t 'bop': { shareSize: 'Large', quantity: '1', itemPrice: '46', message: '' }, 
 
     }, 
 
    \t items: [ 'foo', 'bar', 'baz' ], 
 
     addons: [ 'bop' ], 
 
     selected: {}, 
 
     paymentConfig: { 
 
      advance: 25, 
 
      firstweek: 25, 
 
      ondelivery: 50, 
 
     }, 
 
     weeks: 12, 
 
    }, 
 
    
 
    components: { 
 
     entriesComponent, 
 
    }, 
 
    
 
    created() { 
 
     this.setSelectableItems() 
 
    }, 
 
    
 
    computed: { 
 
    
 
     totalAdvance() { 
 
      return (this.paymentConfig.advance * this.total)/100 
 
     }, 
 
     
 
     totalFirstWeek() { 
 
      return (this.paymentConfig.firstweek * this.total)/100 
 
     }, 
 
     
 
     onDeliveryPayment() {   
 
      return (this.paymentConfig.ondelivery * this.total)/(this.weeks * 100) 
 
     }, 
 
     
 
     total() { 
 
     
 
      var sum = 0 
 
      
 
      Object.keys(this.selected) 
 
       .forEach((productKey) => { 
 
       \t if (this.selected[productKey]) { 
 
         sum += 
 
          this.weeks * 
 
          this.allProducts[productKey].itemPrice * 
 
          this.allProducts[productKey].quantity 
 
        } 
 
       }) 
 
      
 
      return sum 
 
      
 
     }, 
 
     
 
    }, 
 

 
\t methods: { 
 
    
 
    \t setSelectableItems() { 
 
     
 
     \t this.items 
 
       .forEach((productKey) => { 
 
        Vue.set(this.selected, productKey, false) 
 
       }) 
 
       
 
      this.addons 
 
       .forEach((productKey) => { 
 
        Vue.set(this.selected, productKey, false) 
 
       }) 
 
     
 
     }, 
 
    
 
    \t setSelected (productKey, value) { 
 
     
 
     \t this.selected[productKey] = value 
 
     
 
     }, 
 
     
 
     syncItem (key, field, value) { 
 
     
 
     \t this.allProducts[key][field] = value 
 
     
 
     }, 
 
    
 
    }, 
 
    
 
});
.row { 
 
    background: #f1f1f1; 
 
    padding: 25px; 
 
    margin-top: 10px; 
 
} 
 

 
.row:nth-child(even) { 
 
    background: #f9f9f9; 
 
} 
 

 
.item { 
 
    background: #dcdcdc; 
 
    border: 1px solid #a2a2a2; 
 
    padding: 10px; 
 
    margin-top: 10px; 
 
} 
 

 
.item span { 
 
    margin-left: 10px; 
 
} 
 

 
.item input { 
 
    display: inline-block; 
 
}
<script src="https://unpkg.com/vue/dist/vue.js"></script> 
 
<div id="app"> 
 

 
    <div class="row"> 
 
     <label class="control-label required">Items</label> 
 
     <entries 
 
      v-for="productKey in items" 
 
      :update-item="syncItem"   
 
      :item="allProducts[productKey]" 
 
      :item-key="productKey" 
 
      :update-selected="setSelected" 
 
      :selected="selected[productKey]"></entries> 
 
    </div> 
 

 
    <div class="row"> 
 
     <label class="control-label required">Addons</label> 
 
     <entries 
 
      v-for="productKey in addons" 
 
      :update-item="syncItem"  
 
      :item="allProducts[productKey]" 
 
      :item-key="productKey" 
 
      :update-selected="setSelected" 
 
      :selected="selected[productKey]"></entries> 
 
    </div> 
 
    
 
    <div class="row"> 
 
     <label>Summary</label> 
 
     <div class="item" v-for="(value, productKey) in selected" v-if="value"> 
 
      <span>{{ allProducts[productKey].shareSize }}</span> 
 
      <span> 
 
       {{ allProducts[productKey].quantity }} 
 
       x $ 
 
       {{ (allProducts[productKey].itemPrice * allProducts[productKey].quantity).toFixed(2)}} 
 
      </span> 
 
      <span>{{ allProducts[productKey].message }}</span> 
 
     </div> 
 
    </div> 
 
    
 
    <div class="row"> 
 
     <label>Payment plan</label> 
 
     <p>{{ '$ ' + totalAdvance.toFixed(2) }} - advance</p> 
 
     <p>{{ '$ ' + totalFirstWeek.toFixed(2) }} - first week</p> 
 
     <p>{{ '$ ' + onDeliveryPayment.toFixed(2) }}/ week on each of the {{ weeks }} weeks of the subscription</p> 
 
    </div> 
 

 
    <div class="row"> 
 
     <p> 
 
      <span>Total</span> 
 
      <span>{{ '$ ' + total.toFixed(2) }}</span> 
 
     </p> 
 

 
     <p> 
 
      <span>Total due now</span> 
 
      <span>{{ '$ ' + totalAdvance.toFixed(2) }}</span> 
 
     </p> 
 
    </div> 
 

 
</div> 
 

 

 
<!-- component template --> 
 
<template id="entries"> 
 

 
    <div class="item"> 
 

 
     <input 
 
      type="checkbox" 
 
      v-bind:value="selected" 
 
      @change="updateSelected(itemKey, $event.target.checked)"> 
 
     
 
     <span>size: {{item.shareSize}}</span> 
 
     
 
     <span>price: {{'$ ' + Number(item.itemPrice).toFixed(2) }}</span> 
 
     
 
     <input type="number" v-model="quantity" /> 
 
     
 
     <input type="text" v-model="message" /> 
 

 
    </div> 
 

 
</template>

+0

v-model = "allProducts [productKey] .quantity"は私にとってはモデル全体でなければなりません。私は数量を更新するだけでなく、アイテムに他のフィールドも追加します。私はそれが各項目のためのコンポーネントを行うのが最善でないかどうか疑問に思っていましたか? – anegrea

+0

製品の複数のフィールドを更新するための更新された回答 – GuyC

+0

それはあなたのためにそれを並べ替えましたか? – GuyC

関連する問題