I have a component named concepts, with its data and methods.
In another view I have two instance of this component (I'm using vuetify too):
// Index.vue
<template>
<v-card>
<v-toolbar>
<v-toolbar-title>Conceptos</v-toolbar-title>
</v-toolbar>
<v-tabs class="elevation-2" color="primary">
<v-tab>Ordinarios</v-tab>
<v-tab>Extraordinarios</v-tab>
<v-tab-item :key="1">
<concepts :is_extra="false" :key="1"></concepts>
</v-tab-item>
<v-tab-item :key="2">
<concepts :is_extra="true" :key="2"></concepts>
</v-tab-item>
</v-tabs>
</v-card>
</template>
<script>
import concepts from './Concepts.vue'
export default {
components: {
concepts,
},
data() {
return {
}
}
}
</script>
In the concepts component the is_extra property is used as a parameter, In the method created() of the vue instance, the function fetchAll retrieve from API the data correctly, the param is sent with the correct value:
// Concepts.vue
// this works correctly
created() {
const isExtra = this.is_extra //true or false depends of the property value
// GET /concepts?is_extra=true ...or false
this.server
.setParams({ is_extra: isExtra })
.fetchAll()
}
I have a method named upload (to upload a file) where I use this property again, but the value always is false, Always of the first component
...
// Concepts.vue
methods: {
upload() {
const isExtra = this.is_extra // always false
this.server.setParams({is_extra: isExtra}).upload()
}
}
The full Concepts.vue component here:
<template>
<v-data-table
:divider="true"
:headers="headers"
:items="concepts">
<template v-slot:top>
<v-toolbar flat color="white">
<v-spacer></v-spacer>
<template v-if="me.caps.canUploadCsv()">
<v-btn color="secondary" class="mr-2" dark>
Agregar concepto
</v-btn>
<input type="file" class="d-none" id="csv_file" #change="confirm" accept=".csv">
<v-btn #click="selectFile" :loading="uploading" color="green" dark>
<v-icon left>mdi-file-upload</v-icon> Cargar CSV
</v-btn>
</template>
</v-toolbar>
<v-dialog v-model="confirmDialog"
#click:outside="closeConfirm" #keydown="closeConfirm" max-width="320">
<v-card>
<v-card-title>
<span class="headline">Confirmar</span>
</v-card-title>
<v-card-text>
¿Desea continuar con la carga del archivo?
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text #click="closeConfirm">
No
</v-btn>
<v-btn color="primary" dark #click="uploadFile">Si</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<template v-slot:item.description="{ item }">
<span :title="item.description">
{{ item.description.substr(0, 60) }}...
</span>
</template>
<template v-slot:item.amount_formated="{ item }">
$ {{ item.amount_formated }}
</template>
<template v-slot:item.iva_formated="{ item }">
$ {{ item.iva_formated }}
</template>
<template v-slot:item.total_formated="{ item }">
$ {{ item.total_formated }}
</template>
</v-data-table>
</template>
<script>
import { bus } from '../../app'
import User from '../../models/User'
import Concept from '../../models/Concept'
export default {
props: ['is_extra'],
data() {
return {
me: null,
headers: [
{ text: 'Clave', value: 'code' },
{ text: 'Categoría', value: 'category' },
{ text: 'Descripción', value: 'description' },
{ text: 'Unidad', value: 'unity' },
{ text: 'Total', value: 'total_formated', align: 'end' },
],
concepts: [],
model: null,
loaded: false,
inputFile: null,
confirmDialog: false,
uploading: false,
}
},
created() {
this.me = (new User()).getMe()
const params = this.$route.params
this.model = new Concept(params.companyId, params.contractId)
const isExtra = this.is_extra
this.model.server
.setParams({ is_extra: isExtra })
.fetchAll(this.onSuccess)
},
mounted() {
this.inputFile = document.getElementById('csv_file')
console.log('1', this)
},
methods: {
selectFile() {
if (this.uploading) {
return
}
this.inputFile.click()
},
confirm() {
this.confirmDialog = true
},
closeConfirm() {
this.inputFile.value = null
this.confirmDialog = false
},
uploadFile() {
console.log(this)
this.confirmDialog = false
this.uploading = true
const isExtra = this.is_extra
bus.$emit('snackbar', { color: 'info', text: 'Subiendo archivo...' })
this.model.server
.setParams({ is_extra: isExtra })
.upload(null, 'csv', this.inputFile, this.onSuccess)
},
onSuccess(resp) {
if (this.uploading) {
bus.$emit('snackbar', {
color: 'success', text: 'Conceptos actualizados correctamente'
})
}
if (this.inputFile) {
this.inputFile.value = null
}
this.uploading = false
this.concepts = resp.data
},
}
}
</script>
I put a console.log(this) inside of the created and upload methods, when I change the tab (vuetify tabs), in the first case I get:
VueComponent {_uid: 43, _isVue: true, ...} // created(), is_extra=false
VueComponent {_uid: 71, _isVue: true, ...} // created(), is_extra=true
but in the upload method (when upload the file) I get the same instance:
VueComponent {_uid: 43, _isVue: true, ...} // upload() is_extra=false
VueComponent {_uid: 43, _isVue: true, ...} // upload() is_extra=false
I added :key property but it didn't work.
Vue devtools show the two components with its correct data.
Before using vuetify tabs I already had the issue
Can someone help me please?
Related
I have a component that I use in various parts of my application to render tables.
What I want to do now in view of the fact that every time I need to add more custom fields to the table (templates), is to be able to pass these templates as a prop to the parent component so that I do not have to always be editing this component.
As you can see I have tried in many ways and I have not been able to find the solution.
Father component
<template>
<section>
<data-table-search
:titleFilter="titleFilter"
:selectFilter="selectFilter"
:srchfunction="srchfunction"
:clkfunction="clkfunction"
:filterable="filterable"
:itemsFilter="itemsFilter"
:clickSelect="clickSelect"
:btnew="btnew"
:elevationNew="elevationNew"
:btnNewClass="btnNewClass"
:btsmall="btsmall">
</data-table-search>
<div :is="processedHtml"></div>
<v-data-table
class="tableBackground"
:dense="dense"
:headers="headers"
:items="items.data"
:server-items-length="items.recordsFiltered"
:options.sync="options"
:loading="loading"
:footer-props="footerProps"
no-data-text="No hay datos disponibles"
:loading-text="$t('comunes.general.cargando')">
<template v-slot:progress>
<v-progress-linear
height="2"
:color="colorProgress"
indeterminate
></v-progress-linear>
</template>
<template v-if="Object.keys(spanState).length > 0 && spanState.state == true" v-slot:item.state="{ item }">
<div class="">
<span v-if="item.state === 1" color="red">Abierto</span>
<span v-else-if="item.state === 2" color="green">En bodega</span>
<span v-else-if="item.state === 3" color="green">Revisado</span>
<span v-else-if="item.state === 4" color="green">En correo</span>
<span v-else-if="item.state === 5" color="green">Aceptada</span>
<span v-else-if="item.state === 6" color="green">Parcial</span>
<span v-else-if="item.state === 7" color="green">Rechazada</span>
<span v-else-if="item.state === 8" color="green">Orden de trabajo</span>
<span v-else-if="item.state === 9" color="green">Incompleto</span>
<span v-else-if="item.state === 10" color="green">Facturado</span>
<span v-else color="green"></span>
</div>
</template>
<template v-slot:item.activo="{ item }">
<v-icon :small="btsmall" color="green" v-if="item.activo">check_circle</v-icon>
<v-icon :small="btsmall" color="red" v-else>cancel</v-icon>
</template>
<template v-if="actions.length>1" v-slot:item.opciones="{ item }">
<v-menu offset-y small>
<template v-slot:activator="{ on }">
<v-btn :small="btsmall" class="btn-opciones" dark v-on="on">{{ $t('comunes.general.opciones') }}</v-btn>
</template>
<v-list class="dt-actions">
<v-list-item-group v-for="(action, index) in actions" :key="index">
<v-list-item #click="_onClick(action.action, item.id)">
<v-list-item-icon :class="action.color">
<v-icon :small="btsmall" class="text-white" v-text="action.icon"></v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title v-text="action.text"></v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</v-list>
</v-menu>
</template>
<template v-else v-slot:item.opciones="{ item }">
<v-btn :small="btsmall" class="btn-opciones" #click="_onClick(actions[0].action, item.id)" dark v-on="on">{{ btnSeleccionar ? btnSeleccionar : $t('comunes.general.seleccionar') }}</v-btn>
</template>
</v-data-table>
</section>
</template>
<script>
import datatableMixin from '#/mixins/datatable'
import dataTableSearch from '#/components/utilidades/dataTableSearch'
export default {
name: 'datatable',
mixins: [ datatableMixin ],
components: { dataTableSearch },
data () {
return {
on: false,
template: '<h1>Hola</h1>'
}
},
props: {
searchFunction: Function,
clkfunction: Function,
clickSelect: Function,
endpoint: String,
dense: Boolean,
btsmall: Boolean,
// initialData: {
// type: Boolean,
// default: true
// },
re: Function,
initialData: {
type: Boolean,
default () {
return true
}
},
headers: {
type: Array,
default: { }
},
spanState: {
type: Object,
default () {
return {}
}
},
itemsFilter: {
type: Array,
default: Array
},
templates: {},
filterable: {
type: Boolean,
default: false
},
selectFilter: {
type: Boolean,
default: false
},
titleFilter: {
type: String,
default: 'Filtro'
},
btnew: {
type: Boolean,
default: false
},
btnActionClass: {
type: String,
default: ''
},
btnNewClass: {
type: String,
default: ''
},
elevationAction: {
type: Number,
default: 2
},
elevationNew: {
type: Number,
default: 2
},
colorProgress: {
type: String,
default: 'primary'
},
btnSeleccionar: {
type: String,
default: null
},
actions: Array,
endManual: Boolean
},
computed: {
processedHtml () {
// let html = this.html.replace('[Placeholder]', '<my-component></my-component>')
return {
template: this.template
}
}
},
mounted () {
this.getData()
if (Object.keys(this.spanState).length > 0) {
console.log('fds', this.items)
}
},
methods: {
_onClick (event, id) {
this.clkfunction(event, id)
},
async srchfunction (text) {
this.search = text
this.options.page = 1
this.getData()
}
}
}
</script>
Child component:
<template>
<div>
<v-dialog v-if="dialogModalBuscador" v-model="dialogModalBuscador" scrollable max-width="600px">
<v-card>
<v-card-title>
<span class="h2" >{{title}}</span>
</v-card-title>
<v-card-text class="pb-0">
<data-table
:btsmall="true"
:endpoint="endpoint"
:headers="headers"
:filterable="true"
:actions="actions"
:clkfunction="clickFunction"
:initialData="initialDataL"
v-on:changeInitialDatastateEmit="emm"
:showCountOrdenesTecnico="True"
:customTemplate="re"
:endManual="true">
<template
v-for="header in headers"
v-slot:[`item.${header.value}`]="{ item }"
>
<slot :name="[`item.${header.value}`]" :item="item">
{{ getVal(item, header.value) }}
</slot>
</template>
<template v-slot:item="{ item }">
<div class="text-center">
<span v-if="item.countOrdenNoFacturada === 0" color="red">Sin Entregar</span>
<span v-else-if="item.countOrdenNoFacturada === 2" color="green">Solicitado</span>
<span v-else color="green"></span>
</div>
</template>
</data-table>
</v-card-text>
<v-card-actions class="d-block" >
<v-btn color="red" #click="dialogModalBuscador = false" outlined >{{$t('comunes.general.cancelar')}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import configMixin from '#/mixins/config'
import dataTable from '#/components/utilidades/dataTable'
export default {
mixins: [ configMixin ],
components: { dataTable },
data () {
return {
dialogModalBuscador: false,
loading: false,
initialDataL: this.initialData
// templates: `1.0/cda/serviciosproductosobtener/${id}/`
}
},
props: {
title: {
type: String,
default: 'Listado default'
},
endpoint: {
type: String,
default: {}
},
headers: {
type: Array
},
hidden: {
type: Boolean,
default: true
},
initialData: {
type: Boolean,
default: true
},
actions: {
type: Array,
default: () => [ { 'text': 'Seleccionar', 'icon': 'check_box', 'action': 'ver', 'color': 'primary' } ]
}
// endpoint: String
},
mounted () {
},
methods: {
re () {
return { template: `<template v-slot:item.countOrdenNoFacturada="{ item }">
<div class="">
<span v-if="item.countOrdenNoFacturada === 0" color="red">Abiertoooo</span>
<span v-else color="green"></span>
</div>
</template>
` }
},
async clickFunction (event, id) {
if (event === 'ver') this.$emit('getId', id)
if (event === 'editar') this.$router.push({ name: this.openRoute(`cda/formulario/${id}/`) })
if (event === 'crear') this.$router.push({ name: this.openRoute(`cda/formulario/${id}/`) })
},
emm (e) {
console.log('EMMIT', e)
this.initialDataL = e
}
}
}
</script>
You can use v-bind="$attrs". which means that all the attributed passed to the parent component will pass on to the child component.
so in your case use it like so:
parent component:
<data-table-search v-bind="$attrs">
and now you don't need to declare all of those props in the parent component.
I have a delete dialog component that when clicking Cancel or Delete nothing happens, not even errors. What am I missing to correctly delete or cancel
<template>
<v-dialog
v-bind="$attrs"
v-on="$listeners"
max-width="500px"
persistent
>
<v-card>
<v-card-title
class="headline"
>
{{ title }}
</v-card-title>
<v-card-text>
{{ message }}
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
color="grey darken-1"
text
#click="$emit('closeDeleteDialog')"
>
Cancel
</v-btn>
<v-btn
color="primary darken-1"
text
#click="$emit('deleteItem')"
>
Delete
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: 'DeleteDialog',
props: {
title: {
type: String,
required: true
},
message: {
type: String,
default: ''
}
},
emits: ['closeDeleteDialog', 'deleteItem']
}
</script>
This is how I use my component:
<DeleteDialog
v-model="dialogDelete"
title="Delete location"
message="Are you sure you want to delete this location?"
/>
On the same view as where I import my component I have my methods.
export default {
components: {
DeleteDialog: () => import('#/components/Shared/DeleteDialog'),
},
data: () => ({
locationId: null,
dialog: false,
dialogDelete: false,
})
},
methods: {
deleteItem () {
this.$store.dispatch('deleteFirebaseDoc', { docId: this.locationId, collection: 'locations' })
this.locationId = null
this.dialogDelete = false
},
deleteItemConfirm (item) {
this.locationId = item.docId
},
closeDeleteDialog () {
this.dialogDelete = false
}
}
}
</script>
How can I correctly access my component to delete and item or cancel the dialog?
In the parent component you need to to listen to those events you emit
<DeleteDialog
v-model="dialogDelete"
title="Delete location"
message="Are you sure you want to delete this location?"
#close-delete-dialog="dialogDelete = false" // or call closeDeleteDialog ()
#delete-item="deleteItem()"
/>
I've never used camelCase for events emitting so I'd rather write it like $emit('close-delete-dialog') and $emit('delete-item')
I'm trying to create SnackBarComponent.vue so I can implement it in my BaseTemplate.vue where I have my main menu that references the other router-view components.
This would be my BaseComponent.Vue
<template>
<v-app id="inspire">
<v-navigation-drawer
v-model="drawer"
app
clipped
>
<v-list dense>
<v-list-item
v-for="item in items"
:key="item.title"
:to="item.to"
:active-class="`primary white--text`"
link
>
<v-list-item-icon>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar
app
clipped-left
color="blue"
dark
>
<v-app-bar-nav-icon #click.stop="drawer = !drawer"></v-app-bar-nav-icon>
<v-toolbar-title>Title</v-toolbar-title>
</v-app-bar>
<v-main>
<v-container fluid style="padding:30px">
<transition name="component-fade" mode="out-in">
<router-view></router-view>
</transition>
</v-container>
</v-main>
<template>
<v-snackbar
v-model="snackbar"
:timeout="timeoutSnackBar"
>
{{ textSnackBar }}
</v-snackbar>
</template>
</v-app>
</template>
<script>
export default {
data: () => ({
snackbar: false,
timeoutSnackBar: -1,
textSnackBar: '',
methods:{
SnackNotification(time,text){
this.snackbar = true
this.timeoutSnackBar: time
this.textSnackBar: text
}
}
drawer: null,
items: [
{
title: "Home",
icon: "mdi-view-dashboard",
to: "/"
},
{
title: "Users",
icon: "mdi-account",
to: "/users"
},
]
}),
}
</script>
and i try use in de UserComponent.vue
<template>
<v-card
class="mx-auto"
max-width="344"
outlined
>
<v-list-item three-line>
<v-list-item-content>
<div class="overline mb-4">
OVERLINE
</div>
<v-list-item-title class="headline mb-1">
Headline 5
</v-list-item-title>
<v-list-item-subtitle>Greyhound divisely hello coldly fonwderfully</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-avatar
tile
size="80"
color="grey"
></v-list-item-avatar>
</v-list-item>
<v-card-actions>
<v-btn
outlined
rounded
text
>
Button
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
export default {
created() {
this.users();
},
methods: {
users: function() {
axios
.get('/api/users')
.then(response => {
this.users = response.data.data
})
.catch(error => {
this.errored = true
})
.finally(() => {
if (this.firstLoad) this.firstLoad = false
this.loading = false;
this.SnackNotification(2000,'Hi, im a notification')
})
},
}
</script>
My app.js is this.
import App from './components/BaseTemplate.vue'
const app = new Vue({
el: '#app',
render: h => h(App),
vuetify: new Vuetify(),
router
})
had the idea to do it this way but I think I am quite wrong to do this global implementation, I looked for some options but they used NuxtJS and it was not really what I had in mind, any recommendation that could give me how to do it? thank you.
You could add the snack bar in vue.app as global snackbar with vuex.
Example:
App.vue
<template>
<v-app>
...
<v-main>
<router-view />
</v-main>
...
<v-snackbar v-model="snackbar.active" :timeout="-1" :color="snackbar.color">
{{ snackbar.message}}
<template v-slot:action="{ attrs }">
<v-btn text v-bind="attrs" #click="snackbar.active = false">
Close
</v-btn>
</template>
</v-snackbar>
</v-app>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "App",
computed: {
...mapState(["snackbar"])
}
};
</script>
Index.js (store)
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
snackbar: { active: false, color: "", message: "" }
},
mutations: {
SET_SNACKBAR(state, snackbar) {
state.snackbar = snackbar;
}
},
actions: {
snackBar({ commit }, message) {
commit("SET_SNACKBAR", {
active: true,
color: "success", // You can create another actions for diferent color.
message: message
});
}
}
});
Now in any router view you can active the snackbar like this
Example.vue
<template>
...
<v-btn #click="showSnackBar()">
Show SnackBar!
</v-btn>
...
</template>
<script>
import { mapActions} from "vuex";
export default {
methods: {
...mapActions(["snackBar"]),
showSnackBar() {
this.snackBar("Hi, I'm snackbar");
}
}
};
</script>
Please see my answer here for a very similar problem. In that case, they wanted a global 'confirm dialog' but in your case it's a 'global snackbar'
The code that I posted in that answer can be used for a snackbar instead of a dialog with very minimal modification. In fact, in my projects I usually go ahead and add both because they're so useful.
I have the following Dropdown in a Vue.js Project.
<template>
<v-menu close-on-click transition="slide-y-transition">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" v-bind="attrs" v-on="on">
Menu
</v-btn>
</template>
<v-list>
<v-list-item v-for="(item, index) in menuItemsMisc" :key="index">
<v-list-item-title>
<v-btn block color="white">{{ item.title }}</v-btn>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</template>
<script>
export default {
name: 'MenuBar',
data: () => ({
menuItemsMisc: [
{ title: 'Visit Website' },
{ title: 'Logout' },
{ title: 'Purchase' },
]
}),
}
</script>
I want all these buttons to have different functions like:
Visit Website -> Link to a Website
Logout -> To Call a function
Purchase -> A Purchase Modal to appear
That's how I have been handling the drop-down buttons before using page routing.
<v-list-item v-for="(item, index) in menuItemsPages" :key="index">
<v-list-item-title>
<v-btn :to= "'/' + item.url" >{{ item.title }}</v-btn>
</v-list-item-title>
</v-list-item>
But I think Page routing isn't the best way to go if we have buttons Drastically different in functionality. How should I go about it?
(not vuetify)I am not sure if this is the best practice but you can try this:
In my router there is an About page and it works ! Also when we select other options I can see the outputs in console. If you can adapt this code into vuetify, it can work.
<template>
<div class="home">
<select v-model="selectedValue">
<template v-for="(item, index) in menuItemsMisc">
<option :value="item.title" :key="index"> {{item.title }} </option>
</template>
</select>
</div>
</template>
<script>
// # is an alias to /src
export default {
name: 'Home',
data() {
return {
selectedValue : "",
menuItemsMisc: [
{ title: 'Visit Website' },
{ title: 'Logout' },
{ title: 'Purchase' },
]
}
},
watch: {
"selectedValue": function() {
if (this.selectedValue === "Visit Website") {
this.$router.push({name: "About"})
}
else if (this.selectedValue === "Logout") {
this.doSomething()
}
else {
this.purchase()
}
}
},
methods: {
doSomething() {
console.log("I AM DOING SOMETHING")
},
purchase() {
console.log("hello purchase")
}
}
}
</script>
Another way is to define a function to the menuItemsMisc's elements, then pass it to #click of v-btn.
<template>
<v-menu close-on-click transition="slide-y-transition">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" v-bind="attrs" v-on="on">Menu</v-btn>
</template>
<v-list>
<v-list-item v-for="(item, index) in menuItemsMisc" :key="index">
<v-list-item-title>
<!-- Pass `item.click` to `#click` -->
<v-btn block color="white" #click="item.click">{{ item.title }}</v-btn>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</template>
export default {
name: "Home",
data: () => ({
menuItemsMisc: [
{
title: "Visit Website",
click: () => {
// Go to a route
this.$router.push({ name: "About" });
}
},
{
title: "Logout",
click: () => {
// Call a function
console.log("Logging out...");
}
},
{
title: "Purchase",
click: () => {
// Show modal
console.log("Showing purchase modal");
}
}
]
})
};
Here is a sample demo.
You can add a function to each object in your array like so :
menuItemsMisc: [
{ title: 'Visit Website', fn: () => { this.$router.push('/') }},
{ title: 'Logout' , fn: () => { /* Your logic */ }},
{ title: 'Purchase' , fn: () => { /* different logic */ }},
]
and use it with an event listener on click :
<v-btn #click="item.fn" >{{ item.title }}</v-btn>
A combination of both answers worked for me!
data: () => ({
menuItemsMisc: [
{ title: "Vorlage speichern" },
{ title: "Anwesenheit bearbeiten" },
],
)}
watch: {
selectedValue: function () {
if (this.selectedValue === "Vorlage speichern") {
this.saveAsVorlage(this.topListWithName);
} else if (this.selectedValue === "Anwesenheit bearbeiten") {
this.updateAnwesenheit = true;
}
},
},
I have the following vue component and the values are loaded correctly from the store and displayed on the form. However if I change the value in a field it is not updated in the store. How can I make it such that whenever I change a value in the form it is also committed to the store?
<template>
<v-form v-model="valid" justify="center" class="mx-5" :disabled="show">
<v-row justify="center">
<H1 class="my-10">{{coin}}</H1>
</v-row>
<v-row>
<H3 class="my-5 mx-10">Add account</H3>
</v-row>
<v-row justify="space-around">
<v-text-field v-model="settings.key" :rules="[rules.required]" class="mx-12" label="API Key" />
</v-row>
</v-form>
</template>
<script>
import store from '../store'
export default {
name: "Settings",
store,
props: ["coin", "show"],
data: () => ({
valid: true,
rules: {
required: (value) => !!value || "Required.",
},
}),
computed: {
settings: {
get() { return store.getters.getSettingsBySymbol(this.coin) },
set(value) { store.commit("setSettingsBySymbol", value) },
}
},
}
</script>
==== EDIT =====
settings = {
coin: "hh",
key: "12345",
secret: "ajksjlkuT6ty",
}