I have a reactive array that I am trying to determine the best way to handle. It's a standard add/remove but one of the 3 fields that is part of that add/remove section updates one of the others. 1 field is a service the other is the quantity of that service and the third totals the service price + quantity = that field price.
I am having issues working on the indexing and I can't wrap my head around it.
relavent HTML
<div class="col-span-6 gap-4">
<div class="grid grid-cols-6 gap-6" v-for="(service, index) in form.services" :key="index">
<div class="col-span-3 gap-4">
<Label for="service" value="Service" :class="[form.zip_codes == '' ? disableLabel : '']"/>
<v-select label="serviceData" :options="servicesData" v-model="service[index]"
:disabled="form.zip_codes == ''"
class="mt-1 block w-full border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm">
</v-select>
<InputError :message="form.errors.services" class="mt-2"/>
</div>
<div class="col-span-1 gap-4">
<Label for="quantity" value="Quantity" :class="[form.zip_codes == '' ? disableLabel : '']"/>
<Input id="quantity" v-model="service.quantity" type="number" class="mt-1 block w-full"
:disabled="form.zip_codes == ''"
autocomplete="phone_2"
#change="calculatePrice($event.target.value, service[index], index)"/>
<InputError :message="form.errors.quantity" class="mt-2"/>
</div>
<div class="col-span-2 gap-4">
<Label for="price" value="Price"/>
<Input id="price" v-model="servicePrice[index]" type="text" class="mt-1 block w-full" disabled
:disabled="form.zip_codes == ''"
autocomplete="phone_2"/>
<InputError :message="form.errors.quantity" class="mt-2"/>
</div>
<SecondaryButton #click="removeService(index)">Remove</SecondaryButton>
</div>
<div class="pt-5">
<SecondaryButton
:class="{ 'opacity-25': form.processing }"
:disabled="form.processing"
type="button"
#click="addServices()"
>
Add Services
</SecondaryButton>
</div>
my main focus is calculatePrice()
defineProps({
zip_codes: Object,
appointment_types: Array,
servicesData: Object
})
const servicePrice = reactive([])
const calculatePrice = (quantity, service, index) => {
servicePrice.push( Math.round((quantity * service.price) * 100) / 100);
}
As you can see I can push a new value to it but I am not sure how to set it to the correct index. I tried servicePrice[index] but it just returns -1.
Ref or Recative are instantaneous changing values.
You can watch the relevant fields with watch, if there is a change, you can make the calculation.
watch(() => servicePrice.value ,() => {
servicePrice.value = Math.round((quantity * service.price) * 100) / 100;
})
Related
I got the problem in making program for my company, the concept is you can input mark (nilai) for every sector based on kriteria of the mark you had to fill and it has 5 kriteria. the problem is I have to separate the kriteria based on the kriteria name and when I try the array cant be shown
<template>
<div class="space-x-4 sm:-my-px sm:ml-1 sm:flex">
<jet-button #click="getKriteria1">P1</jet-button>
<jet-button #click="getKriteria2">P2</jet-button>
<jet-button #click="getKriteria3">P3</jet-button>
<jet-button #click="getKriteria4">P4</jet-button>
<jet-button #click="getKriteria5">P5</jet-button>
</div>
<div class="mt-4">
<div class="space-x-4 sm:-my-px sm:ml-1 sm:flex" v-if="session === 1" :v-for="(kriteria, index) in kriteria1.data" :key="kriteria.id">
<label>{{kriteria.sub_kriteria}} : </label>
<jet-input type="number" class="mt-1 block w-3/4" placeholder="Nilai"
ref="nilai"
v-model="form.nilai[index]"
#keyup.enter="create" />
<jet-input-error :message="form.errors.nilai" class="mt-2" />
</div>
</div>
</template>
can you guys help me why the kriterias i get cant be show, in the console i can see the kriteria is read and has field but when i try to call it with props it cant be shown and cant be convert to kriteria1
<script>
props: {
penilaians: Array,
kriterias:Array,
},
data() {
return {
session:1,
kriteria1:[],
kriteria2:[],
kriteria3:[],
kriteria4:[],
kriteria5:[],
form:this.$inertia.form({
nilai:[],
foto:[],
status:[],
rekomendasi:[]
}),
}
},
methods:{
getKriteria1(){
this.session = 1;
this.kriteria1 = kriterias;
for(let index=0;index<=kriterias.length;index++){
if(kriterias[index].nama === 'P1'){
this.kriteria1[index].id = kriterias[index].id;
this.kriteria1[index].nama = kriterias[index].nama;
this.kriteria1[index].sub_kriteria = kriterias[index].sub_kriteria;
}
}
},
}
</script>
i erase the component and import in purpose because it will not affect the question i think
the main idea is to filter the 'kriteria' field to spesific values so i made the filter with getKriteria 1 so i can get 'nilai' form for the 'kriteria'
method:{
getKriteria1(){
this.session = 1;
var kriteria = this.kriterias;
var j=0;
for(var i=0;i<= kriteria.length;i++){
if(kriteria[i].nama == 'P1'){
this.kriteria1[j] = kriteria[i];
j++;
}
}
},
}
this is the jetstream template of the program :
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="space-x-4 sm:-my-px sm:ml-1 sm:flex" :v-on:show ="getPenilaianId()">
<jet-button v-on:click.prevent="getKriteria1()" >P1</jet-button>
<jet-button v-on:click.prevent="getKriteria2()" >P2</jet-button>
<jet-button v-on:click.prevent="getKriteria3()" >P3</jet-button>
<jet-button v-on:click.prevent="getKriteria4()" >P4</jet-button>
<jet-button v-on:click.prevent="getKriteria5()" >P5</jet-button>
</div>
<div class="mt-4">
<div v-if="session === 1">
<div v-for="item in kriteria1" :key="item.id" :v-on:show="getKriteriaId(item.id-1)">
<div v-if="item === null"> Tidak ada Kriteria </div>
<label>{{item.nama}} - {{item.sub_kriteria}}</label>
<jet-input type="number" class="mt-1 block w-3/4" placeholder="Nilai"
ref="nilai"
v-model="form.nilai[item.id-1]"
#keyup.enter="create" />
<jet-input-error :message="form.errors.nilai" class="mt-2" />
</div>
</div>
</div>
Sorry. I face some problem on how to display the data that nested in array.(Vue js)
Here is the return array
I would to show the data in total_billed_by_year
I tried several other attempts but nothing works.
Could please someone help me out with this?
getInfo(index){
this.popup = true;
this.inquiryForm.total_contractual=this.pageData.ppr_data[index].total_contractual;
this.inquiryForm.bil_year =this.pageData.ppr_data[index].total_billed_by_year[index].bil_year;
this.inquiryForm.bil_total_amount =this.pageData.ppr_data[index].total_billed_year.bil_total_amount;
},
<vs-popup :active.sync="popup">
<div class="vx-row mb-base">
<div class="vx-col lg:w-1/2 w-full mb-base">
<vx-card
title="Total Bill"
icon="/images/task.png"
headerClass="bg-dark pb-6"
titleColor="#fff"
subtitleColor="#fff"
>
<template slot="no-body">
<div
id=""
class="transition-all duration-500 ease-in-out p-4"
>
<div class="grid lg:grid-cols-3 grid-cols-1">
<div class="mt-5 ml-2">
<h5>Total Contractual Amount</h5>
<div class="text-lg">
<div v-if="inquiryForm.total_contractual">
<div>RM {{inquiryForm.total_contractual}} </div>
</div><div v-else>-</div></div>
</div>
<div class="mt-5 ml-2">
<h5>Bill {{inquiryForm.bil_year}} </h5>
<div class="text-lg">
<div>RM {{inquiryForm.bil_total_amount}}
</div>
</div>
</div>
</div>
</template>
</vx-card>
</div>
</div>
</vs-popup>
<vs-list-item
class="hover:shadow"
v-for="(tr, index) in ppr"
v-bind:key="index"
>
<template slot="subtitle">
<div #click="getInfo(index)" class="cursor-pointer">{{tr.id}}</div>
</template>{{tr.total_billed_by_year[index].bil_year}}
<span class="font-bold truncate overflow-auto">{{tr.month}} -{{tr.year}}
<p v-for="(bill,ind) in tr.total_billed_by_year" v-bind:key="ind">
{{bill.bil_year}}{{bill.bil_total_amount}}
</p>
</span>
</vs-list-item>
I think the easiest way would be make your column total_bil_year to return as a array via casting from its model. Something like below (if total_billed_by_year column is a json column)
protected $casts = [
'total_billed_by_year' => 'array'
];
Based on the image you attached to the question shows that it is returned as a json. So you can convert it as object at vue also. Something like below
JSON.parse(tr.total_billed_by_year) which will convert into a array and that array contain the object. See the below image. I just reproduced it at console
you can use it like below. Or just make a function to convert your jsons to objects where you can use it when you want
</template>{{JSON.parse(tr.total_billed_by_year)[0].bil_year}}
baby, using JSON.parse(yourJSONString) to transform your json string to json object.
I am using vue-select in my project along with tabulator. I was able to fetch data from json file and view it. But when selecting the options i get an error saying " Component emitted event "option:selecting" but it is neither declared in the emits option nor as an "onOption:selecting" prop. ". I could not resolve this error after multiple try. Below is the code.
**<template>
<form>
<div class="container h-25 w-10/12 mx-auto pb-3 border 2 border-gray-300 flex flex-col rounded-md items-left bg-gray-100" >
<label class="px-3 py-1 w-10/12 text-xs text-black font-medium">Employee</label>
<div class="px-2">
<v-select v-model="Selected" multiple :options="options" label="Employee" placeholder="---SELECT---" class="style-chooser"></v-select>
</div>
<!-- <span>Selected: {{ Employee_Id }}</span> -->
</div>
</form>
<!-- <ul><li v-for="item in datas" :key="item.Employee">{{ item.Employee }}</li></ul> -->
</template>
<script>
import dataset from './dataset.json'
export default {
data(){
return {
openCard: false,
Selected: ""
}
},
computed: {
options: () => dataset
},
methods:{
open(){
this.openCard = ! this.openCard
},
},
}
</script>**
Your help is highly appreciated la.
This is my code i'm trying to get the sum from input values .
It works fine when i enter numbers but as soon as i clear any input field i get total as NaN. i know using parseInt for number value is troubling , but if i'm not using parseInt it appends number instead of getting doing Sum on input Values .
I want to solve it ? why NaN is coming and how to make this code error free .. don't want to use if else for NaN or IsNan please suggest practical approach --
<template>
<div>
<form #submit.prevent="submit" autocomplete="off">
<div class="form-group d-flex mt-3">
<label for="zero" class="p-2 bg-info text-white redius-5">0</label>
<input style="width:100px;" min="0" class="form-control" name="zero" id="zero" v-model.number="zero" #click="doSum" v-model="fields.zero" oninput="validity.valid||(value=''); " />
<div v-if="errors && errors.zero" class="text-danger">{{ errors
.zero[0] }}</div>
<label for="one" class="p-2 bg-info text-white">1</label>
<input style="width:100px;" min="0" type="number" class="form-control" name="one" v-model.number="one" id="one" #click="doSum" v-model="fields.one" oninput="validity.valid||(value=''); "/>
<div v-if="errors && errors.one" class="text-danger">{{ errors.one[0] }}</div>
<label for="two" class="p-2 bg-info text-white">2</label>
<input style="width:100px;" min="0" type="number" class="form-control" name="two" v-model.number="two" id="two" #click="doSum" v-model="fields.two" oninput="validity.valid||(value=''); " />
<div v-if="errors && errors.two" class="text-danger">{{ errors.two[0] }}</div>
</div>
Total = {{ Bettotal }}
</form>
</div>
<script>
export default {
props: ['game_id', 'userId', 'this.rows'],
mounted() {
console.log('Component mounted.')
},
data() {
return {
timestamp: 0,
selectedGame: {},
gamesinfo: [],
zero:0,
one:0,
two:0,
Bettotal:0,
gamex: this.gameId,
rows: [],
count: 0,
fields: {},
errors: {},
success: false,
loaded: true,
};
},
doSum: function () {
this.Bettotal = parseInt(this.zero) + parseInt(this.one) + parseInt(this.two);
// if (isNaN(this.Bettotal)) this.Bettotal = 0;
return this.Bettotal;
},
};
In your total() method instead of
acc += parseInt(row.value)
try:
acc += (row.value - 0)
I think that simple hack should work because it will convert it to number when you subtract zero from empty string.
ok i have added a validator and now its not giving me NaN
oninput="this.value = Math.abs(this.value);
I have a very basic hide/show div function set up for when people click a certain radio button. In one of the hidden divs I need to create a form however when I add input fields to the hidden div my function stops working.
<div id="tabs">
<div id="nav">
<input type="radio" name="primary_contact_director" value="Yes" class="div1">Yes</input>
<input type="radio" name="primary_contact_director" value="No" class="div2">No</input>
</div>
<div id="div1" class="tab">
<p>this is div 1</p>
</div>
<div id="div2" class="tab">
<p>this is div 2</p>
</div>
</div>
<script type="text/javascript" charset="utf-8">
(function(){
var tabs =document.getElementById('tabs');
var nav = tabs.getElementsByTagName('input');
/*
* Hide all tabs
*/
function hideTabs(){
var tab = tabs.getElementsByTagName('div');
for(var i=0;i<=nav.length;i++){
if(tab[i].className == 'tab'){
tab[i].className = tab[i].className + ' hide';
}
}
}
/*
* Show the clicked tab
*/
function showTab(tab){
document.getElementById(tab).className = 'tab'
}
hideTabs(); /* hide tabs on load */
/*
* Add click events
*/
for(var i=0;i<nav.length;i++){
nav[i].onclick = function(){
hideTabs();
showTab(this.className);
}
}
})();
This code works however when I add
<label class="title">First Name:</label>
<input type="text" name="first_name" class="form">
<label class="title">Last Name:</label>
<input type="text" name="last_name" class="form">
<label class="title">Business Address:</label>
<span class="instructions">Please enter a physical address. P.O. Boxes are not acceptable for filing.<br>
If your business is run out of your home, please list that address.</span><br>
<input type="text" name="business_address" class="form">
<label class="title">City:</label>
<input type="text" name="business_city" class="form">
<label class="title">State</label>
<select name="business_state">
<option value="California">California</option>
</select>
<label class="title">Zip Code:</label>
<input type="text" name="business_zip" class="form">
<label class="title">Business Phone Number:</label>
<input type="text" name="business_phone" class="form"><br>
to my div2 it stops working.
Hopefully this is a clear explanation. Any help is always appreciated!
In your hideTabs() function, you've got two typos.
First, you're iterating through the tab[] array, but you're checking it against the length of the nav[] array. This works because you have the same number of elements in your first example, but that's just a coincidence. If you evaluate it against the tab[] array's length, it will work better. The other problem you have is that your for loop ends at greater-than-or-equal-to length. THe problem is that arrays start counting at zero, so if the length is 3, the items on the list are tab[0], tab[1], and tab[2]. your code was trying to set something for tab[3], which didn't exist.
Here's the working code:
/*
* Hide all tabs
*/
function hideTabs(){
var tab = tabs.getElementsByTagName('div');
for(var i=0;i<tab.length;i++){
if(tab[i].className == 'tab'){
tab[i].className = tab[i].className + ' hide';
}
}
}
In the future, you should look into using the javascript console in Chrome (or any other browser) to check for errors if your scripts stop working—usually there's an error that that will give you hints as to what's happening.