3

I am dynamically adding new row with selects and inputs in table if option is selected in first column of last row.

It looks like this https://jsfiddle.net/zgykgery/ so when you select 'Service' new row is added and total price of that row is calculated taking service price, default 10% discount and amount.

I am getting service price a bit clumsy with :value="item.id+'|'+item.price" so I have filter to take it from value. But it works and now I don't know how I can loop through all rows and sum price of service without dicount, sum discount and then full price with servce price and discount.

I know I should use computed properties or watcher but don't know how.

How can I compute sum of those values in table and display them in smaller table below?

Update

I am new in vue and didn't use computed properties so this is what I tried but without success:

var Main = {
  data() {
    return {
      rows_top: [{
        service: '',
        position: '',
        visit: '',
        amount: '',
        discount: 10
      }],
      services: [{
          id: 1,
          name: 'Service1',
          price: 100
        },
        {
          id: 2,
          name: 'Service2',
          price: 200
        },
        {
          id: 3,
          name: 'Service3',
          price: 300
        },
      ],
      total_discount: 0,
      total_full_price: 0
    }
  },
  methods: {
    addRow(row, index) {
      // console.log(row)
      if (this.rows_top[this.rows_top.length - 1].service !== '') {
        this.rows_top.push({
          service: '',
          position: '',
          visit: '',
          amount: '',
          discount: 10
        })
      }
    },
    deleteRow(index) {
      this.rows_top.splice(index, 1)
    }
  },
  computed: {
    total_price: () => {
      if (this.rows_top) {
        return this.rows_top.map((r) => {
          return r.amount * this.$options.filters.after_line(r.service)
        })
      }
    }
  },
  filters: {
    after_line: (value) => {
      if (!value) return ''
      let after = value.split('|')
      return after.pop()
    }
  }
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
@import url("//unpkg.com/[email protected]/lib/theme-chalk/index.css");
table {
  border-collapse: collapse
}

table,
th,
td {
  border: 1px solid #ddd
}

th,
td {
  padding: 5px
}

tr:nth-child(odd) {
  background-color: #f9f9f9
}
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/[email protected]/lib/index.js"></script>
<div id="app">
  <template>
  <table>
  <thead>
    <tr>
      <th>Service</th>
      <th>Position</th>
      <th>Visit</th>
      <th>Amount</th>
      <th>Price</th>
      <th>Discount %</th>
      <th>Full price</th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="(row, index) in rows_top">
      <td>
        <el-select placeholder="Select" filterable="filterable" @change="addRow(row, index)" v-model="row.service">
          <el-option v-for="item in services" :key="item.id" :label="item.name" :value="item.id+'|'+item.price"></el-option>
        </el-select>
      </td>
      <td>
        <el-select placeholder="Select" v-model="row.position" multiple="multiple" filterable="filterable" allow-create="allow-create" @change="checkNumber(result, index)"></el-select>
      </td>
      <td>
        <el-select placeholder="Select" v-model="row.visit" allow-create="allow-create" filterable="filterable">
          <el-option v-for="i in 10" :key="i" :label="i" :value="i"></el-option>
        </el-select>
      </td>
      <td>
        <el-select placeholder="Select" v-model="row.amount" allow-create="allow-create" filterable="filterable">
          <el-option v-for="i in 30" :key="i" :label="i" :value="i"></el-option>
        </el-select>
      </td>
      <td>{{ row.service | after_line }}</td>
      <td>
        <el-input v-model="row.discount"></el-input>
      </td>
      <td><span v-if="row.service && row.amount">{{ ($options.filters.after_line(row.service) * row.amount - (($options.filters.after_line(row.service) * row.amount) / 100) * row.discount).toFixed(2) }}</span><span v-else-if="row.service">{{ ($options.filters.after_line(row.service) - ($options.filters.after_line(row.service) / 100) * row.discount).toFixed(2) }}</span>
        <el-button v-if="row.service" icon="el-icon-delete" size="mini" @click="deleteRow(index)" class="push-right"></el-button>
      </td>
    </tr>
  </tbody>
</table><br/>
<table>
  <tr>
    <td>Total price</td>
    <td>{{ total_price }}</td>
  </tr>
  <tr>
    <td>Total discount</td>
    <td>{{ total_discount }}</td>
  </tr>
  <tr>
    <td>Total full price</td>
    <td>{{ total_full_price }}</td>
  </tr>
</table>
</template>
</div>

Here is also updated fiddle and total price is still empty on change https://jsfiddle.net/zgykgery/21/

4
  • Use a computed. Just write the function that does the calculation and make that the computed. Commented Feb 18, 2018 at 17:36
  • @RoyJ thanks, yes I assumed computed should be used but I am new in that. Can you check am I on right track in updated question? Thanks Commented Feb 18, 2018 at 18:25
  • Welcome to Stack Overflow. Please put a Minimal, COMPLETE, Verifiable, Example IN THE QUESTION ITSELF. Just linking to a jsfiddle is not enough. Just putting a few lines in your question is not enough. Commented Feb 18, 2018 at 18:33
  • @gman ok, I added full code to question Commented Feb 18, 2018 at 18:38

1 Answer 1

1

As @Roy J said, just use a computed function to get you the values of your calculation, knowing that it will automatically change when the data from item changes

EDIT: a simple method is more designed in the case when you use a v-for loop

methods: {
    priceID (item) {
        return item.id + '|' + item.price
    }
}

And you would use it simply like that in your Vue

<tr v-for="(row, index) in rows_top">
  <td>
    <el-select placeholder="Select" filterable="filterable" @change="addRow(row, index)" v-model="row.service">
      <el-option v-for="item in services" :key="item.id" :label="item.name" :value="priceID(item)"></el-option>
    </el-select>
  </td>
  ...
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks but with this I am getting that item is undefined. Can you check updated question?
Didn't see the item variable come from your v-for loop, you then just have to pass a parameter to the function (i.e priceID) which will be item. But as you're using a v-for loop to get item, there's no point using a computed so you can fallback to a standard function in methods. Updated my answer accordingly
Thanks for that but I don't know if you understand what I need. I need sum of values in rows that are dynamically added with that select. Like described in question. Is this method that you proposed helping me get that in some way?
Ofc, you can pass whatever you need to count your rows to the function !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.