[Vuejs]-VueJS: How can I edit all components of the same type in App.vue

1👍

You could set a property in the data object for currency and use that across all components and have a function alter it.

data() {
  return {
    currency: "USD",
    ...
  }
},
methods: {
  changeCurrency(newCurrency){
    this.currency = newCurrency;
  }
}

and in the template

<span @click=changeCurrency('Euro')> Change currency </span>

1👍

I don’t know if I got the logic of your problem but maybe you can use the vue props like this:

      <FruitPrices fruit="apple" :currency="newCurrency || 'USD'"></FruitPrices>
      <FruitPrices fruit="banana" :currency="newCurrency || 'GBP'"></FruitPrices>
      <FruitPrices fruit="orange" :currency="newCurrency || 'USD'"></FruitPrices>

you can define the props currency inside the component FruitPrices. If the currency prop is not defined then the second currency is going to be taken as default (for example "newCurrency || 'GBP'" if newCurrency is null then the currency GBP is taken as default).

Vue docs for props: https://v2.vuejs.org/v2/guide/components-props.html

Then in the main template component, you define the variable newCurrency and you pass that variable to the prop currency of the component FruitPrices:

data: () => {
    newCurrency: null
},
methods: {
    setNewCurrency() {
        this.newCurrency = this.someFieldOfYourForm;
    }
}
👤Dan

1👍

Let’s use this component to pass the currency, price and fruit to each component FruitPrices component:

<template>
  <div>
    <!-- USD is selected by default, once the option change, the prices will be updated -->
    <select v-model="currency">
      <!-- allows to select one currency at time, it shows all the currencies
          that exist in the currencies array data property -->
      <option
        v-for="(currencyOption, index) in currencies"
        :key="index"
        :value="currencyOption"
      >
        <!-- show only the currency name as option -->
        {{ currencyOption.name }}
      </option>
    </select>
    <div v-for="(fruit, fruitIndex) in fruitsWithPrices" :key="fruitIndex">
      <!-- if everything is working fine, you don't need close tags for empty
          custom component, you can use '/' at the end of the first tag to self close it-->
      <FruitPrices :name="fruit.name" :convertedPrice="fruit.convertedPrice" />
    </div>
  </div>
</template>
<script>
import FruitPrices from '../somePlace/FruitPrices'
export default {
  name: "FruitPricesContainer",
  components: { FruitPrices },
  data: () => ({
    fruits: [
      {
        name: 'Apple',
        price: 0.2
      },
      {
        name: 'Banana',
        price: 0.3
      },
      {
        name: 'Orange',
        price: 0.25
      }
    ],
    currency: {
      // Base currency, exchangeRate = 1
      exchangeRate: 1,
      name: 'USD'
    },
    // Used exchange rates only for demo purpose, not are the real and valid exchange rates
    currencies: [
      {
        exchangeRate: 1,
        name: 'USD'
      },
      {
        exchangeRate: 1.2,
        name: 'EUR'
      },
      {
        exchangeRate: 0.7,
        name: 'SGD'
      },
      {
        exchangeRate: 700,
        name: 'MXN'
      },
      {
        exchangeRate: 3700,
        name: 'COP'
      }
    ]
  }),
  computed: {
    // The fruitsWithPrices listen for changes in both, the fruit and
    // the currency, so once you change it by selecting a different currency
    // the prices will be updated automatically (nice)
    fruitsWithPrices() {
      return this.fruits.map((fruit) => {
        return {
          ...fruit, // Add name and original price to the returned object
          convertedPrice: fruit.price * this.currency.exchangeRate // Add the price based on the exchange rate
        }
      })
    }
  }
}
</script>

Now, let’s create the FruitPrices component:

<template>
  <div>
    <p>{{ name }}: {{ convertedPrice }}</p>
  </div>
</template>
<script>
export default {
  name: "FruitPrices",
  props: {
    name: {
      type: String,
      required: true
    },
    convertedPrice: {
      type: Number,
      required: true
    }
  }
}
</script>

And it’s ready! (Tbh, I didn’t test it, please let me know if you have errors or problems).

Leave a comment