<template>
<div>
<template v-for="i in 9">
<div v-if="i != 2 && i != 3 && i != 7 && i != 8 && i != 9" :key="i">
<v-chip>
{{ i }}
</v-chip>
</div>
<v-chip :key="i" v-else>
{{ i }}
</v-chip>
</template>
</div>
</template>
This snippet generates this output
How to render exactly this output but horizontally to get this
if you consider using an array from data option, this might work
<template>
<div>
<template v-for="(i, index) in items">
<div v-if="!isNaN(i)" :key="index">
<v-chip>
{{ i }}
</v-chip>
</div>
<div style="display: inline" v-else :key="index">
<v-chip v-for="(n, index) in i" :key="index">
{{ n }}
</v-chip>
</div>
</template>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
items: [1, [2, 3], 4, 5, 6, [7, 8, 9]],
};
},
};
</script>
You can use Chip group component
Demo :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
sizes: [
'1', '2', '3', '4', '5', '6', '7', '8', '9'
],
}),
})
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.4/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.4/dist/vuetify.min.css"/>
<div id="app">
<v-app id="inspire">
<v-chip-group
v-model="selection"
>
<v-chip
v-for="size in sizes"
:key="size"
:value="size"
>
{{ size }}
</v-chip>
</v-chip-group>
</v-app>
</div>
Related
I have an expansion panel and a v-for on it. I want to keep the panel with the same id as the logged-in user on top, and the others render last. My code is like it now:
<v-expansion-panels>
<v-expansion-panel v-for="(sign, index) in demandSignatures" :key="index">
<v-expansion-panel-header
#click="dataEdit(sign)"
:hide-actions="userID !== sign.userEid"
:disabled="userID !== sign.userEid"
>
<v-row>
<v-col cols="1"></v-col>
<v-col cols="4">
{{ sign.userFullName }}
</v-col>
<v-col>
<span
v-if="sign.signatureStatus === 'Accepted'"
class="text-success"
>امضا شده</span
>
<span
v-else-if="sign.signatureStatus === 'Rejected'"
class="text-danger"
>رد شده</span
>
<span
v-else-if="sign.signatureStatus === 'pending'"
class="text-warning"
>در انتظار تایید</span
>
</v-col>
</v-row>
</v-expansion-panel-header>
<v-expansion-panel-content v-if="userID === sign.userEid">
<v-divider />
<v-card-text class="mt-3">
<v-textarea
label="توضیحات"
v-model="description"
outlined
dense
></v-textarea>
</v-card-text>
<v-card-actions class="mx-4 justify-end d-flex">
<v-btn
class="me-2"
icon
small
#click="signForm(sign.eid, 'Accepted', acceptText)"
>
<v-icon small color="teal">mdi-draw-pen</v-icon>
</v-btn>
<v-btn
class="ms-2"
icon
small
#click="signForm(sign.eid, 'Rejected', rejText)"
>
<v-icon small color="red">mdi-close</v-icon>
</v-btn>
</v-card-actions>
<v-divider />
</v-expansion-panel-content>
<v-expansion-panel-content v-else></v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
I want to keep the panel with this condition v-if="userID === sign.user-id on top
Can anyone help with it?
Modify your demandSignatures data by plucking the item whose id is equal to userID and put it in the first position. You can do this job on the mounted hook.
Here is the working demo-
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
</head>
<body>
<div id="app">
<v-app>
<v-expansion-panels>
<v-expansion-panel v-for="(sign, index) in demandSignatures" :key="sign.userEid">
<v-expansion-panel-header
#click="dataEdit(sign)"
:hide-actions="userID !== sign.userEid"
:disabled="userID !== sign.userEid"
>
<v-row>
<v-col cols="1"></v-col>
<v-col cols="4">
{{ sign.userFullName }}
</v-col>
<v-col>
<span
v-if="sign.signatureStatus === 'Accepted'"
class="text-success"
>امضا شده</span
>
<span
v-else-if="sign.signatureStatus === 'Rejected'"
class="text-danger"
>رد شده</span
>
<span
v-else-if="sign.signatureStatus === 'pending'"
class="text-warning"
>در انتظار تایید</span
>
</v-col>
</v-row>
</v-expansion-panel-header>
<v-expansion-panel-content v-if="userID === sign.userEid">
<v-divider />
<v-card-text class="mt-3">
<v-textarea
label="توضیحات"
v-model="description"
outlined
dense
></v-textarea>
</v-card-text>
<v-card-actions class="mx-4 justify-end d-flex">
<v-btn
class="me-2"
icon
small
#click="signForm(sign.eid, 'Accepted', acceptText)"
>
<v-icon small color="teal">mdi-draw-pen</v-icon>
</v-btn>
<v-btn
class="ms-2"
icon
small
#click="signForm(sign.eid, 'Rejected', rejText)"
>
<v-icon small color="red">mdi-close</v-icon>
</v-btn>
</v-card-actions>
<v-divider />
</v-expansion-panel-content>
<v-expansion-panel-content v-else></v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
userID: 3,
description: null,
demandSignatures: [{
userEid: 1,
userFullName: "I am not equal to userID",
signatureStatus: "Accepted"
},
{
userEid: 2,
userFullName: "I am not equal to userID",
signatureStatus: "pending"
},
{
userEid: 3,
userFullName: "I am equal to userID",
signatureStatus: "Rejected"
},
{
userEid: 4,
userFullName: "I am not equal to userID",
signatureStatus: "Rejected"
},
],
};
},
mounted() {
this.reOrder();
},
methods: {
reOrder() {
// Find the index of item who match with userID
let index = this.demandSignatures.findIndex(
(item) => item.userEid == this.userID,
);
// If item found
if (index != -1) {
// save it in some local variable
let item = this.demandSignatures[index];
// remove it from its current position
this.demandSignatures.splice(index, 1);
// and put it at the first position
this.demandSignatures.unshift(item);
}
},
dataEdit() {},
signForm() {},
},
})
</script>
</body>
</html>
I wanna know how to v-for on a multidimensional array with selected index, because when I go with this code it does not work.
<div v-for="button in pull.button_response[key]">
<p>test</p>
</div>
Thank you
Try this:
//===== just to remove warnings
Vue.config.productionTip = false;
Vue.config.devtools = false
//==============================
new Vue({
el: "#app",
data: {
pull: {
button_response: {
a: [
1, 2, 3, 4, 5
],
b: [
6, 7, 8, 9, 10
]
}
},
key: ['a', 'b']
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template>
<div>
<select v-model="key">
<option value="a">a</option>
<option value="b">b</option>
</select>
<br/>
<div v-for="button in pull.button_response[key]">
<p>{{button}}</p>
</div>
</div>
</template>
</div>
You can use both, index and object like an enum, so
<div v-for="(index, button) in pull" :key="index">
<p>test {{ button[index] }}</p>
</div>
expansion-panel and when I delete one from the array it automatically opens the next one for me.
how can I undo it?
Thanks
<v-expansion-panel
v-for="(Test, index) in Test"
:key="index">
<v-expansion-panel-header>
<template v-slot:actions>
<v-icon color="green">fa fa-check</v-icon>
</template>
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-col cols="4">
<v-btn
text
color="primary"
#click="
delete(Test)
"
>delete</v-btn
>
</v-col>
</v-expansion-panel-content>
</v-expansion-panel>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
active: null,
test: [1, 2, 3, 4, 5]
}),
methods: {
del(index) {
this.test.splice(index, 1)
this.active = null
}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-expansion-panels v-model="active">
<v-expansion-panel v-for="(t, index) in test" :key="index">
<v-expansion-panel-header>
item
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-col cols="4">
<v-btn text color="red" #click="del(index)">delete{{t}}</v-btn>
</v-col>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-container>
</v-main>
</v-app>
</div>
Using value prop:
Controls the opened/closed state of content in the expansion-panel. Corresponds to a zero-based index of the currently opened content.
Set this.active = null after each deletion to keep the panel closed.
Vuetify provides a select field component that is used for collecting user provided information from a list of options.
Here for the documentation
The component works with check boxes, so each time you check an item, it is added at the end of the list.
Now what I'd like to do is adding the same item on the list multiple times, so each time you click the item it is added at the end of the list. Is this achievable with Vuetify?
So the image is a bit misleading. If you would like to get tag input with autosuggestions, then I would rather keep it separate.
It would be possible to enhance the example below with v-text-field, but feels kinda hacky to me.
Please let me know how does this solution suite you :)
new Vue({
el: '#app',
vuetify: new Vuetify({ icons: { iconfont: 'md' } }),
data: () => ({
options: [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'fizz' }],
value: [
{ id: 1, name: 'foo' },
{ id: 1, name: 'foo' }
],
}),
})
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-row>
<v-col cols="12" sm="12">
<v-chip class='mr-2' v-for='({id, name}, i) in value'>
{{ id }}: {{ name }}
<v-icon class='ml-2' small #click='value.splice(i, 1)'>close</v-icon>
</v-chip>
<v-menu>
<template v-slot:activator='{ on }'>
<v-btn icon v-on='on' class='green'>
<v-icon>add</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item v-for='o in options' #click='value.push(o)'>
<v-list-item-title>{{ o.name }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-col>
<v-col>
<pre>{{ value }}</pre>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
If you have items with same name, you need to use it's distinct property (here it is "id") to tell the difference.
and use item-text & item-value as shown in the example.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'foo' },
{ id: 4, name: 'fizz' },
{ id: 5, name: 'bar' }],
value: null,
}),
})
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-row align="center">
<v-col cols="12" sm="6">
<v-select v-model="value" :items="items" item-text="name" item-value="id" attach chips label="Chips" multiple></v-select>
</v-col>
<v-col>
<pre>{{ value }}</pre>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
I wanted to create simple invoice using bootstrap table and Vue Js.
Basically, What i wanted is shown in the image below:
I have tried as in the code below, but i am confused on two things,
How should i
1) Calculate the total cost and show that as the footer summary.
2) Multiply rate and qnty and display on the corresponding input box on cost.
new Vue({
el: '#app',
methods: {
addService() {
this.model.services.push({});
}
},
data: {
model: {
services: []
},
fields: [{
key: "rate",
label: "Rate"
},
{
key: "qnty",
label: "Qnty"
},
{
key: "cost",
label: "Cost"
}
]
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css" />
<script src="https://unpkg.com/vue"></script>
<script src="//unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
<div id="app">
<b-card header-tag="header" footer-tag="footer">
<template slot="header" class="mb-0">
<button type="button" class="btn btn-primary btn-sm" #click.prevent="addService">
<icons :icon="['fas', 'plus']" /> Add Items/Service</button>
</template>
<b-card-body>
<b-table responsive bordered striped hover caption-top :fields="fields" :items="model.services" foot-clone>
<template slot="rate" slot-scope="data">
<b-form-input size="sm" class="form-control" v-model="data.item.rate" :name="`rate_${data.index}`" type="text" />
</template>
<template slot="qnty" slot-scope="data">
<b-form-input size="sm" class="form-control" v-model="data.item.qnty" :name="`qnty_${data.index}`" type="text" />
</template>
<template slot="cost" slot-scope="data">
<b-form-input size="sm" class="form-control" v-model="data.item.cost" :name="`cost_${data.index}`" type="text" />
</template>
</b-table>
</b-card-body>
</b-card>
</div>
The way i wanted is easily achieved by using normal td and tr, with computed function.
But i am confused with how to implement using Bootstrap-vue.
Please help!
Here's a quick way, that calculates the item cost in place
<b-form-input :value="(data.item.rate * data.item.qnty) || 0" type="text" />
Improvements can be made here to update the item total in the item, by using a watch t update the data.
the total, however is done using a computed value that uses reduce to find the total
computed: {
total: function() {
return this.model.services.reduce(function(a, c){return a + Number((c.rate*c.qnty) || 0)}, 0)
}
},
here is the complete code:
Vue.config.productionTip = false
Vue.component('icons', {
template: '<a><slot></slot></a>'
})
new Vue({
el: '#app',
methods: {
addService() {
this.model.services.push({});
}
},
computed: {
total: function() {
return this.model.services.reduce(function(a, c){return a + Number((c.rate*c.qnty) || 0)}, 0)
}
},
data: {
model: {
services: []
},
fields: [{
key: "rate",
label: "Rate"
},
{
key: "qnty",
label: "Qnty"
},
{
key: "cost",
label: "Cost"
}
]
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css" />
<script src="https://unpkg.com/vue"></script>
<script src="//unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
<div id="app">
<b-card header-tag="header" footer-tag="footer">
<template slot="header" class="mb-0">
<button type="button" class="btn btn-primary btn-sm" #click.prevent="addService">
<icons :icon="['fas', 'plus']" /> Add Items/Service</button>
</template>
<b-card-body>
<b-table responsive bordered striped hover caption-top :fields="fields" :items="model.services" foot-clone>
<template slot="rate" slot-scope="data">
<b-form-input size="sm" class="form-control" v-model="data.item.rate" :name="`rate_${data.index}`" type="text" />
</template>
<template slot="qnty" slot-scope="data">
<b-form-input size="sm" class="form-control" v-model="data.item.qnty" :name="`qnty_${data.index}`" type="text" />
</template>
<template slot="cost" slot-scope="data">
<b-form-input size="sm" class="form-control" :value="(data.item.rate * data.item.qnty) || 0" :name="`cost_${data.index}`" type="text" />
</template>
<template slot="bottom-row" slot-scope="data">
<td/><td>Total</td>
<td>{{total}}</td>
</template>
</b-table>
</b-card-body>
</b-card>
</div>