When passing params from a select, the usual syntax would be something like this.
<v-select
v-model="item_id"
items="items"
item-text="item_name"
item-value="id"
#change='itemDescription()'
/>
export default {
data: ()=> ({
item_id: '',
items: [],
itemDescription '',
}),
method: {
itemDescription() {
axios.get('/api/item', {
params: { id: this.item_id }
})
.then(response => this.itemDescription = response.data )
}
}
}
Now the problem comes when the select is inside an array.push. I can't simply pass the value to this.item_id since the structure would be object[0][1]. Here is an example syntax below.
<v-btn #click="addItem()">Add</v-btn>
<template v-for="item in items" :key="item.id>
<v-select
v-model="item.item_id"
items="item_all"
item-text="item_name"
item-value="id"
#change='itemDescription()'
/>
</template>
export default {
data: ()=> ({
items: [],
item_all: '',
}),
method: {
addItem() {
this.items.push({
item_id: '',
description: '',
}),
itemDescription() {
axios.get('/api/item', {
params: { id: this.items.item_id } // <-- this doesn't work
})
.then(response => this.items.description = response.data )
}
}
}
How do I pass id of each row every time I select each one of them?
I made it work now. I just used index, this was my savior.
Please see code below for those interested
<v-btn #click="addItem()">Add</v-btn>
<template v-for="(item, index) in items" :key="item.id>
<v-select
v-model="item.item_id"
items="item_all"
item-text="item_name"
item-value="id"
#change='itemDescription(index)'
/>
</template>
export default {
data: ()=> ({
items: [],
item_all: '',
itemDescription '',
}),
method: {
addItem() {
this.items.push({
item_id: '',
description: '',
}),
itemDescription(index) {
axios.get('/api/item', {
params: { id: this.items[index].item_id } // <-- this doesn't work
})
.then(response => this.items[index].description = response.data )
}
}
}
The 'this' in itemDescription method isn't same as 'this' in 'method:'.
so it will not work.
use another variable to keep this, and use it in itemDescription.
method: {
var that = this;
addItem() {
this.items.push({
item_id: '',
description: '',
}),
itemDescription() {
axios.get('/api/item', {
params: { id: that.items.item_id } // 'this' ain't work
})
.then(response => this.items.description = response.data )
}
Related
I hava a component with complex nested props:
<template>
<div>
<a-tree :tree-data="data" :selected-keys="[selectedKey]" #select="onSelect" />
<div>
<a-input v-model="sheet[selectedKey].tableName" />
<ux-grid ref="previewTable">
<ux-table-column v-for="field in sheet[selectedKey].fields"
:key="field.name" :field="field.name">
<a-input slot="header" v-model="field.label" />
</ux-table-column>
</ux-grid>
</div>
</div>
</template>
<script>
export default {
props: {
previewData: { type: Array, default: () => [] }
},
data () {
return {
data: this.previewData,
selectedKey: '0-0-0',
sheet: { 'none': { tableName: null, fields: [] } }
}
},
created () {
this.data.forEach((file, fid) => {
file.sheets.forEach((sheet, sid) => {
this.$set(this.sheet, `0-${fid}-${sid}`, {
tableName: sheet.label,
fields: sheet.fields.map(field => ({ ...field }))
})
})
})
},
mounted () {
this.$refs.previewTable.reloadData(this.data[0].sheets[0].data)
},
methods: {
onSelect ([ key ], { node }) {
if (key !== undefined && 'fields' in node.dataRef) {
this.selectedKey = key
this.$refs.previewTable.reloadData(node.dataRef.data)
} else {
this.selectedKey = 'none'
this.$refs.previewTable.reloadData()
}
}
}
}
</script>
And previewData props is something like:
{
name: "example.xlsx",
filename: "80b8519f-f7f1-4524-9d63-a8b6c92152b8.xlsx",
sheets: [{
name: "example",
label: "example",
fields:[
{ label: "col1", name: "col1", type: "NUMBER" },
{ label: "col2", name: "col2", type: "STRING" }
]
}]
}
</script>
This component allows user to edit the label properties. I have to make Object sheet reactive to user input, and I tried $set and Object.assign, it works for sheets.label but fields[].label is still not reactive.
I wish to know what would be the declarative (and optimal) solution for it
You might need a watcher or computed property in React for previewData to be changed.
I have a parent component that lists all the tasks:
<template>
<div class="tasks-wrapper">
<div class="tasks-header">
<h4>{{ $t('client.taskListingTitle') }}</h4>
<b-button variant="custom" #click="showAddTaskModal">{{ $t('client.addTask') }}</b-button>
</div>
<b-table
striped
hover
:items="tasks"
:fields="fields"
show-empty
:empty-text="$t('common.noResultsFound')">
</b-table>
<AddTaskModal />
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import AddTaskModal from '#/components/modals/AddTaskModal'
import moment from 'moment'
export default {
name: 'TaskListing',
components: {
AddTaskModal
},
data () {
return {
tasks: [],
fields: [
{ key: 'createdOn', label: this.$t('tasks.tableFields.date'), formatter: 'formatDate' },
{ key: 'domain', label: this.$t('tasks.tableFields.task') },
{ key: 'comment', label: this.$t('tasks.tableFields.comment') },
{ key: 'status', label: this.$t('tasks.tableFields.status') }
]
}
},
computed: {
...mapGetters('users', ['user'])
},
methods: {
...mapActions('tasks', ['fetchTasks']),
...mapActions('users', ['fetchUserById']),
formatDate: function (date) {
return moment.utc(date).local().format('DD.MM.YYYY HH:mm')
},
showAddTaskModal () {
this.$bvModal.show('addTaskModal')
}
},
async mounted () {
const currUserId = this.$router.history.current.params.id
if (this.user || this.user.userId !== currUserId) {
await this.fetchUserById(currUserId)
}
if (this.user.clientNumber !== null) {
const filters = { clientReferenceNumber: { value: this.user.clientNumber } }
this.tasks = await this.fetchTasks({ filters })
}
}
}
</script>
Inside this component there is a child which adds a task modal.
<template>
<b-modal
id="addTaskModal"
:title="$t('modals.addTask.title')"
hide-footer
#show="resetModal"
#hidden="resetModal"
>
<form ref="form" #submit.stop.prevent="handleSubmit">
<b-form-group
:invalid-feedback="$t('modals.requiredFields')">
<b-form-select
id="task-type-select"
:options="taskTypesOptions"
:state="taskTypeState"
v-model="taskType"
required
></b-form-select>
<b-form-textarea
id="add-task-input"
:placeholder="$t('modals.enterComment')"
rows="3"
max-rows="6"
v-model="comment"
:state="commentState"
required />
</b-form-group>
<b-button-group class="float-right">
<b-button variant="danger" #click="$bvModal.hide('addTaskModal')">{{ $t('common.cancel') }}</b-button>
<b-button #click="addTask">{{ $t('modals.addTask.sendMail') }}</b-button>
</b-button-group>
</form>
</b-modal>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'AddTaskModal',
data () {
return {
comment: '',
commentState: null,
taskTypesOptions: [
{ value: null, text: this.$t('modals.addTask.taskType') },
{ value: 'OnBoarding', text: 'Onboarding' },
{ value: 'Accounts', text: 'Accounts' },
{ value: 'TopUp', text: 'Topup' },
{ value: 'Overdraft', text: 'Overdraft' },
{ value: 'Aml', text: 'Aml' },
{ value: 'Transfers', text: 'Transfers' },
{ value: 'Consultation', text: 'Consultation' },
{ value: 'TechnicalSupport', text: 'TechnicalSupport' },
{ value: 'UnblockPin', text: 'UnblockPin' },
{ value: 'Other', text: 'Other' }
],
taskType: null,
taskTypeState: null
}
},
computed: {
...mapGetters('users', ['user']),
...mapGetters('tasks', ['tasks'])
},
methods: {
...mapActions('tasks', ['addNewTask', 'fetchTasks']),
...mapActions('users', ['fetchUserById']),
async addTask (bvModalEvt) {
bvModalEvt.preventDefault()
if (!this.checkFormValidity()) { return }
const currUserId = this.$router.history.current.params.id
if (this.user || this.user.userId !== currUserId) {
await this.fetchUserById(currUserId)
}
const data = {
clientPhone: this.user.phoneNumber,
comment: this.comment,
clientReferenceNumber: this.user.clientNumber,
domain: this.taskType
}
await this.addNewTask(data)
if (this.user.clientNumber !== null) {
const filters = { clientReferenceNumber: { value: this.user.clientNumber } }
this.tasks = await this.fetchTasks({ filters })
// this.tasks may be useless here
}
console.log(this.tasks)
this.$nextTick(() => { this.$bvModal.hide('addTaskModal') })
},
checkFormValidity () {
const valid = this.$refs.form.checkValidity()
this.commentState = valid
this.taskTypeState = valid
return valid
},
resetModal () {
this.comment = ''
this.commentState = null
this.taskTypeState = null
}
}
}
</script>
When I add a task I call getalltasks to mutate the store so all the tasks are added. Then I want to render them. They are rendered but the property createdOn on the last task is InvalidDate and when I console log it is undefined.
The reason I need to call gettasks again in the modal is that the response on adding a task does not return the property createdOn. I do not want to set it on the front-end, I want to get it from the database.
I logged the store and all the tasks are added to the store.
Why is my parent component not rendering this particular createdOn property?
If I refresh the page everything is rendering fine.
If you add anything into a list of items that are displayed by v-for, you have to set a unique key. Based on your explanation, I assume that your key is the index and when you add a new item, you mess with the current indexes. Keys must be unique and unmutateable. What you need to do is to create a unique id for each element.
{
id: Math.floor(Math.random() * 10000000)
}
When you create a new task, use the same code to generate a new id, and use id as key. If this doesn't help, share your d-table and related vuex code too.
I am trying to pass the data from methods into my empty array rows ,how i can easly pass it or how to call the API into rows
export default {
data () {
return {
data: {
headers: [
{ title: 'id', key: 'id' },
{ title: 'name', key: 'name' },
{ title: 'city', key: 'city' },
{ title: 'address', key: 'address' }
],
rows: []
}
}
},
components: {
BaseTable
},
methods: {
fetchUsers () {
this.$axios.get('https://605c40b36d85de00170d9a8f.mockapi.io/user/zurich')
.then(({ data }) => {
this.tableData = data
console.log(data)
})
}
}
}
When the response from your api arrives, you just have to add to your property declared in the method data.
new Vue({
el: "#app",
data() {
return {
row: []
}
},
methods: {
fetching() {
fetch('https://rickandmortyapi.com/api/character')
.then(res => res.json())
.then(res => {
console.log(res);
this.row = res.results; //Results added into array
})
.catch(err => console.error(err))
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="fetching">Fetch Api</button>
<div v-for="(item, key) in row" :key="key" style="margin: 2rem auto;" >
<p>- {{ item.id }} | {{ item.name }} | {{ item.status }}</p>
</div>
</div>
Currently i am trying to get the value of altLanguages and output that dynamically in a JSON, so it can be injected into the head. The altLanguages are the meta attribute values that should be added before rendering the page to avoid the error (altLanguages is undefined). Anyone know how to do that.
<template>
<header class="site-header">
<router-link to="/" class="logo">Example Site</router-link>
<nav>
<ul>
<li v-for="menuLink in menuLinks" :key="menuLink.id">
<prismic-link :field="menuLink.link">{{ $prismic.richTextAsPlain(menuLink.label) }}</prismic-link>
</li>
</ul>
</nav>
<alternate-languages :altLanguages="altLanguages" />
<!-- <alternate-content :altLanguages="altLanguages" /> -->
</header>
</template>
<script>
export default {
props: {
id: { type: String, default: "" },
altLanguages: { type: Array, default: () => ([]) }
},
data() {
return {
menuContent: [],
menuLinks: [],
// altLanguages: []
};
},
methods: {
async getMenu(lang) {
//Query to get menu content
const menuContent = await this.$prismic.client.getSingle("menu", {
lang: lang
});
this.menuContent = menuContent;
this.menuLinks = menuContent.data.menu_links;
}
},
created() {
// this.getLanguages(this.id);
this.getMenu(this.$route.params.lang);
},
watch: {
$route(to, from) {
this.getMenu(to.params.lang);
}
}
// beforeRouteUpdate(to, from, next) {
// console.log("new");
// this.getMenu(to.params.lang);
// next();
// }
};
</script>
//expected output
export default {
data: function () {
return {
title: 'My Title'
}
},
// Usage with context the component
head: {
// To use "this" in the component, it is necessary to return the object through a function
title: function () {
return {
inner: this.title
}
},
meta: [
// altLanguages should be output in here.....
{ name: 'description', content: 'My description', id: 'desc' }
]
}
...
}
}
I made a data table with vue vuetify and I fetch my data from my api server.
In my table, everything is display except boolean.
Can you help me to see clearer
Table component
<template>
<v-data-table
:headers="headers"
:items="fixture"
:items-per-page="5"
class="elevation-10"
>
</v-data-table>
</template>
<script>
export default {
name: 'my_fixtures',
props: ['fixture'],
data () {
return {
headers: [
{ text: 'name',value: 'name'},
{ text: 'State', value: 'on' },
{ text: 'Group', value: 'group' },
{ text: 'Recipe', value: 'recipe' },
{ text: 'start', value: 'startDate' },
{ text: 'end', value: 'endDate' },
{ text: 'Action', value: 'action' },
],
items: this.fixtures
}
}
}
</script>
In the object that I receive , the key 'on' is a Boolean.
I have all display , but nothing in the 'on' column
and this is what I do with props
<template>
<v-container>
<my_fixtures v-bind:fixture="fixtures"></my_fixtures>
<router-view></router-view>
</v-container>
</template>
<script>
import my_fixtures from "./greenhouse/fixtures";
export default {
name: "my_client",
data: function (){
return {fixtures: []}
},
components: {my_fixtures},
mounted() {
http.get('fixture/client')
.then(result => {
this.fixtures = result;
})
.catch(error => {
console.error(error);
});
}
}
</script>
Process and print data using methods.
try this.
<td class="text-xs-right">{{ computedOn(props.fixture.on) }}</td>
export default {
methods: {
computedOn (value) {
return String(value)
}
}
}
UPDATE
Modifying original data due to vuetify bug
https://github.com/vuetifyjs/vuetify/issues/8554
export default {
mounted() {
http.get('fixture/client')
.then(result => {
this.fixtures = result.map(value => {
value.on = String(value.on)
})
})
.catch(error => {
console.error(error);
});
}
}