Can someone help me in sum values in VueJs
im try to get a sum of products
All my products display in select options tag by v-for
Im add event on click and after this im get price value in method
If someone have info about solved this problem im so gratefull
this is my code in Vue component
<div class="form-group row">
<label class="typo__label col-sm-3 col-form-label">Продукты</label>
<div class="col-sm-9">
<multiselect selectLabel="Выбрать" deselectLabel="Удалить" selectedLabel="Выбрано" #input="setSelected"
:taggable="true" v-model="formData.products" :options="this.$store.state.order.products" :multiple="true"
:hideSelected="true" :custom-label="titleWithPrice" :close-on-select="false" :clear-on-select="false"
:preserve-search="true" placeholder="Выберите продукты" label="title" track-by="id" :preselect-first="true">
<template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single"
v-if="values.length && !isOpen">{{ values.length }} options selected</span></template>
</multiselect>
</div>
</div>
this is my code in method
setSelected(value) {
let prices = value;
prices.forEach((price) => {
this.price = price.price
})
}
this is my code in computed
totalItem: function(){
let sum = 0;
this.items.forEach(function(item) {
sum += (parseFloat(item.price));
});
return sum;
}
If the formData.products is correctly setting the values selected, then you can directly get the sum of values from the computed section.
computed:{
sum : function(){
let products = this.formData.products;
return products.reduce((a,b)=>{
return parseFloat(a.price) + parseFloat(b.price);
})
}
}
Related
I can't find anything relevant online. The relevant answers online dont use the tag.
Does it even work with script setup?
<template>
<div class="bg-white md:container md:mx-auto w-10">
<ul class="flex flex-wrap p-2 justify-center bg-black text-white">
<li class="p-2">
Filter
</li>
<li class="p-2">
Search
</li>
</ul>
<div class="flex flex-wrap justify-center h-52 content-center">
<div class="flex justify-center">
<div class="mb-3 xl:w-96">
<label
for="exampleSearch2"
class="form-label inline-block mb-2 text-gray-700"
>Search</label
>
<input
v-model="searchValue"
type="search"
class="form-control block w-full px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none"
id="exampleSearch2"
placeholder="Type query"
/>
<div class="flex flex-wrap">
<div>Test: {{ searchValue }}</div>
</div>
</div>
</div>
</div>
<div class="grid lg:grid-cols-4 md:grid-cols-3 gap-8">
<dogCard v-for="breed in breedsArray" :key="breed.id" :breed="breed" />
</div>
</div>
</template>
<script setup>
import dogCard from "../components/dogCard.vue";
import { ref, onMounted, computed } from "vue";
import searchBox from "./searchBox.vue";
let URL = "https://api.thedogapi.com/v1/breeds";
const searchValue = ref("");
let breedsData = ref([]);
// Fetching API Data
function getBreedsArray() {
fetch(URL)
.then((response) => response.json())
.then((data) => {
breedsData.value = data;
console.log("Data Fetched", breedsData.value);
})
.catch((error) => {
console.error(error);
});
}
onMounted(() => {
getBreedsArray();
});
const breedsArray = computed({
get() {
return breedsData.value;
},
set(val) {
breedsData.value = breedsData.value.filter((breed) => breed.name.includes() == searchValue);
},
});
let isVisible = ref(false);
</script>
Im trying to filter the dogCard through a Searchbox. I just don't know how to do it.
The Data of 'breedsData' should change on when something is entered in the Searchbox.
Thanks in advance, I'm stuck for so long now, an i dont how to fix this.
In the filter() in the computed setter, you do:
(breed) => breed.name.includes() == searchValue
But you probably want to use the value of the ref instead of the ref itself, and put it into includes():
(breed) => breed.name.includes(searchValue.value)
Note that this would permanently remove filtered breeds, as you change the breedsData.value. A better approach might be to just use the computed getter (I don't think the setter works the way you want it to anyway):
const breedsArray = computed(() => searchValue.value ?
breedsData.value.filter( breed => breed.name.includes(searchValue.value)) :
breedsData.value
)
Since searchValue is reactive, a change to it will trigger an update of the breedsArray.
I have this custom component in vue callled "dm-vehicle-spec"
<dm-vehicle-spec #_handleRemoveSpec="_handleRemoveSpec" v-for="spec, index in vehicleSpecs" :key="index" :index="index" :spec="spec"></dm-vehicle-spec>
which looks like the following
<script>
export default {
props: ["spec"],
data() {
return {
specName: null,
specValue: null,
}
},
mounted() {
if (this.spec.detail_name && this.spec.detail_value) {
this.specName = this.spec.detail_name;
this.specValue = this.spec.detail_value;
}
},
computed: {
getSpecNameInputName() {
return `spec_${this.spec.id}_name`;
},
getSpecValueInputName() {
return `spec_${this.spec.id}_value`;
},
},
methods: {
_handleRemoveSpec() {
this.$emit("_handleRemoveSpec", this.spec.id);
}
},
}
</script>
<template>
<div class="specs-row flex gap-2 w-full items-center">
<div class="col-1 w-5/12">
<input placeholder="Naam" type="text" :id="getSpecNameInputName" class="w-full h-12 spec_name rounded-lg border-2 border-primary pl-2" v-model="specName">
</div>
<div class="col-2 w-5/12">
<input placeholder="Waarde" type="text" :id="getSpecValueInputName" class="w-full h-12 spec_name rounded-lg border-2 border-primary pl-2" v-model="specValue">
</div>
<div #click="_handleRemoveSpec" class="col-3 w-2/12 flex items-center justify-center">
<i class="fas fa-trash text-lg"></i>
</div>
</div>
</template>
so when i have 3 specs, 1 from the database and 2 customs i have the following array vehicleSpecs (Which i loop over)
[
{"id":23,"vehicle_id":"1","detail_name":"Type","detail_value":"Snel","created_at":"2022-11-07T19:06:26.000000Z","updated_at":"2022-11-07T19:06:26.000000Z","deleted_at":null},
{"id":24},
{"id":25}
]
so lets say i want to remove the second item from the list so the one with test1 as values, then the array looks like
[{"id":23,"vehicle_id":"1","detail_name":"Type","detail_value":"Snel","created_at":"2022-11-07T19:06:26.000000Z","updated_at":"2022-11-07T19:06:26.000000Z","deleted_at":null},{"id":25}]
So the second array item is removed and thats correct because object with id 24 no longer exsist but my html shows
that the value for object with id 24 still exists but the value for object with id 25 is removed, how is that possible?
If u need any more code or explaination, let me know
Any help or suggestions are welcome!
Index is not a good choice to use as v-for key.
Indexes are changing when you delete something from array.
Try using another property as a key.
Run the loop in reverse order. This way, deleted items do not effect the remaining item indexes
Hit: indexReverse = list.length - index
I have a problem with event, emit and props (and probably some logic too)
I have a component A in which I have a loop with a component B.
In this loop, I have a method to open the modal (which is a component C) but this method is not part of component B.
Like this :
<a>
<!-- MODAL-->
<div v-if="showModal">
<modal-cat #cat="catId = getCatId($event)" #addTx="addTx($event)"></modal-cat>
</div>
<div v-if="transactions.length != 0" class="mx-auto">
<div v-for="tx in transactions" :key="tx">
<div class="mb-2 border border-gray-600 rounded-lg bg-white pt-2 pb-4">
<div class="flex justify-end">
<span
class="inline-flex items-center justify-center h-6 w-6 rounded-full text-lg bg-blue-800 text-white"
#click="showModal = true, txToAdd = tx">
<i class='bx bx-plus'></i>
</span>
</div>
<transaction-data :transaction="tx" :address="walletAddress"></transaction-data>
</div>
</div>
</div>
</a>
In this modal, I fetch some data (in fact, a array of categories) that I also display in a loop.
Like this :
<div class="modal-container">
<div v-for="(categorie) in categories" :key="categorie">
<p #click="$emit('cat', categorie.id)">{{ categorie.name}}</p>
</div>
<div class="modal-footer">
<slot name="footer">
<button class="modal-default-button" #click="$emit('addTx', 'ok')">
OK
</button>
</slot>
</div>
</div>
I need some data from my modal in my component A but I also need some data from my component B in my component A (to add a transactions to a category)
I managed to get the data I wanted like this (And I can get it):
const showModal = ref(false);
const txToAdd = ref({});
const catId = ref(0);
function getCatId(event) {
return event
}
const addTx = (value) => {
if (value === "ok") {
//console.log(txToAdd.value); <= the value are well displayed in the console.
let data = {
tx: txToAdd.value,
catId: catId.value
}
store.dispatch("categories/addTxToCategories", data);
}
}
But in my store, when I try to get the payload, I can't access to the data and I only get the payload object.
Is there something wrong with my logic ? What am I doing wrong ?
EDIT
I just need to wrap the result in spread operator, like this :
const addTx = (value) => {
if (value === "ok") {
//console.log(txToAdd.value);
let data = {
tx: {...txToAdd },
catId: catId.value
}
store.dispatch("categories/addTxToCategories", {...data });
}
}
And in my store, the payload MUST be the second argument :
async addTxToCategories({ commit }, payload) {}
I am working on a Vue Assignment. For styling I am using BootstapVue. What I need to achieve is, whenever an user is entering a text in the input field, a filtered array that is containing the value should be displayed as dropdown. The User can either press Enter key stroke or select the value from dropdown. If the input text is not in the array, then the user should not be able to enter the value i.e. the tag might not be created. For example, whenever we are creating a question here in Stack Overflow, upon typing tags and entering or selecting from the suggestion cards. I I need similar functionality except that if the input text is not in the suggestion array, the user will not be able to create the tag
Here's what I have tried so far :
App.vue
<template>
<div>
<b-form-tags
v-model="value"
#input="resetInputValue()"
tag-variant="success"
:state="state"
>
<template v-slot="{ tags, inputId, placeholder, addTag, removeTag }">
<b-input-group>
<b-form-input
v-model="newTag"
list="my-list-id"
:id="inputId"
:placeholder="placeholder"
:formatter="formatter"
#keypress.enter="addTag(newTag)"
></b-form-input>
</b-input-group>
<b-form-invalid-feedback :state="state">
Duplicate tag value cannot be added again!
</b-form-invalid-feedback>
<ul v-if="tags.length > 0" class="mb-0">
<li
v-for="tag in tags"
:key="tag"
:title="`Tag: ${tag}`"
class="mt-2"
>
<span class="d-flex align-items-center">
<span class="mr-2">{{ tag }}</span>
<b-button
size="sm"
variant="outline-danger"
#click="removeTag(tag)"
>
remove tag
</b-button>
</span>
</li>
</ul>
<b-form-text v-else>
There are no tags specified. Add a new tag above.
</b-form-text>
</template>
</b-form-tags>
<datalist id="my-list-id">
<option>Manual Option</option>
<option v-for="(size, ind) in sizes" :key="ind">{{ size }}</option>
</datalist>
</div>
</template>
<script>
export default {
data() {
return {
newTag: "",
value: [],
sizes: ["Small", "Medium", "Large", "Extra Large"],
};
},
computed: {
state() {
// Return false (invalid) if new tag is a duplicate
return this.value.indexOf(this.newTag.trim()) > -1 ? false : null;
},
},
methods: {
resetInputValue() {
this.newTag = "";
},
formatter(value) {
if (this.sizes.includes(value)) {
return value.toUpperCase();
}
return ;
},
},
};
</script>
How can I achieve the same? Thanks
You can achieve it by using b-form-datalist with the use of <b-form-input> by adding a change event to reset the input value if there is no data in the dataList as per the search value.
Demo :
new Vue({
el: '#app',
data: {
sizes: ['Small', 'Medium', 'Large', 'Extra Large'],
tag: null
},
methods: {
checkTag(e) {
const tagsAvailable = this.sizes.filter((item) => item === e);
if (!tagsAvailable.length) {
this.tag = ''
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.21.2/bootstrap-vue.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.21.2/bootstrap-vue.min.css"/>
<div id="app">
<b-form-input list="my-list-id" v-model="tag" v-on:change="checkTag($event)"></b-form-input>
<datalist id="my-list-id">
<option>Manual Option</option>
<option v-for="size in sizes">{{ size }}</option>
</datalist>
</div>
I am new to vueJS.I am using vue2. I have 3 components catalogue.vue,sellingPrice.vue and profit.vue. Catalogue.vue is a list of all products with a cost price,selling price and a profit percentage. Selling price and profit percentage are individual components inside the catalogue components.Scenario is, when selling price is edited, profit should be automatically calculated and when profit is input manually selling price should be automatically calculated. I am having difficulty passing the profit percentage to catalogue.
I tried using $emit in profit and $on in catalogue. I dont see that working. Can someone help me figure this out.
Profit.vue.
<template id="profit">
<div>
<div v-if="!isActive" #click="toggle()">
<span>{{ calculateProfit }}%</span>
</div>
<div v-if="isActive" class="control has-icons-right">
<input v-model="calculateProfit" class="input is-medium" type="text" placeholder="Text input">
<div class="icon-container is-pulled-right">
<span class="icon is-medium is-right edit-success" #click="emitProfitPercentage()">
<i class="fas fa-check is-success" />
</span>
<span class="icon is-medium is-right edit-cancel" #click="toggle()">
<i class="fas fa-times" />
</span>
</div>
</div>
</div>
</template>
computed:{
calculateProfit:{
get(){
let profPercentage = 0;
if(this.product.profit > 0){
profPercentage = this.product.profit;
}else{
let profitPercentage = 0;
let profitAmt = 0;
if(this.product.sellingCost === 0){
profitPercentage = 0;
}else if(this.product.calculatedLandedPrice > 0 && this.product.sellingCost > 0){
profitAmt = this.product.sellingCost - this.product.calculatedLandedPrice;
profitPercentage = Math.round((profitAmt/this.product.cost)*100);
}else if(this.product.calculatedLandedPrice === 0 && this.product.sellingCost > 0){
profitAmt = this.product.sellingCost - this.product.cost;
profitPercentage = Math.round((profitAmt/this.product.cost)*100);
}
profPercentage= profitPercentage;
}
return profPercentage;
},
set(newValue){
this.product.profit = newValue;
}
},
},
methods:{
toggle() {
this.isActive = !this.isActive;
},
emitProfitPercentage(){
console.log('calculateProfit:', this.product.profit);
this.$emit('update-profit',this.product.profit);
this.toggle();
}
}
Catalogue.vue:
updateSellingPrice(profit){
console.log('profit:', profit);
}
Also tried using this.$on inside created. That doesn't seem to work as well.