[Vuejs]-Calculate the values received from the descendants in VUE

0๐Ÿ‘

โœ…

I solved my problem by using a reactive sessionstorage from vueUse

let sessionOrder = useSessionStorage("basket", [] as SessionOrderType[]);

const calculateOverallTotalSum = (id: number, type: string, sum: number) => {
  if (sessionOrder.value.some((p) => p.id === id && p.type.includes(type))) {
    sessionOrder.value.map((p) => {
      if (p.id === id && p.type === type) {
        return (p.sum = sum);
      }
    });
  } else {
    let obj = {
      id: id,
      type: type,
      sum: sum,
    };
    sessionOrder.value.push(obj);
  }

  summary.value = sessionOrder.value.reduce(
    (total, item) => item.sum + total,
    0
  );
};
๐Ÿ‘คFrallen

1๐Ÿ‘

Some advice:

  • If the value of the variable is not changing, declare it as a constant.
  • As much as possible, declare event handler functions if you want to update reactive states based on DOM events. As your component grows in size, it can be tiring scrolling back-and-forth from the script tag to the template tag to check which DOM event updates the state/s. Furthermore, you can better handle complex computations with it.
  • If a state is dependent on another state, and that state updates on DOM events, move them inside the event handler.

Child Component

<template>
  <!-- Sample template -->
  <div @click.prevent="calculateTotal('sub')">-</div>
  <div @click.prevent="calculateTotal('add')">+</div>
</template>

<script setup>
  import { ref } 'vue';

  const props = defineProps(/** your props */);
  const emit = defineEmits(["remove", "sum"]);

  const count = ref(0);
  const sum = ref(0);

  /** Handler for the @click event */
  const calculateTotal = (operation) => {
    if (operation === 'add') {
      count.value += 1;
    } else if (operation === 'sub' && count.value > 0) {
      count.value -= 1;
    }

    // You don't need to parseInt unless the value is not a number.
    sum.value = count.value * props.item.attributes.Price;

    emit('sum', { id: props.item.id, sum: sum.value });
  };
</script>

Now, in your parent component, render your child components using v-for. Then, declare a state that contains the overallTotalSum of your basket. Finally, like the child component, create a handler that will grab the emitted basket item sum then do the necessary computation.

Parent Component

<template>
  <BasketItem
    v-for="item in items"
    :key="item.id"
    :item="item"
    @sum="calculateOverallTotalSum"
  />
</template>

<script setup>
  import { ref } 'vue';
  import BasketItem from 'path';

  const items = ref([/** your basket items */]);
  const overallTotalSum = ref(0);

  const calculateOverallTotalSum ({ id, sum }) => {
    items.value = items.value.map(item => {
      if (item.id === id) {
        item.sum = sum;
      }

      return item
    });

    overallTotalSum.value = items.value.reduce(
      (total, item) => item.sum + total, 0
    );
  };
</script>

Leave a comment