How to set dynamic v-model for input and set value to this v-model in Vue 2 - vue.js

I have a component for creating dynamic input fields. I have a prop - fields.
fields: [
{
label: 'Question Text',
placeholder: 'Enter Text',
isRequired: true,
editable: true,
name: 'question',
value: '123',
},
{
label: 'Button Text',
placeholder: 'Enter Text',
isRequired: true,
editable: true,
name: 'button',
value: '',
},
],
Than I pass this to component SettingsViewFields.vue
<template>
<div>
<e-form-group v-for="(field, index) in fields" :key="index" :error="getInputError[field.name]">
<template v-slot:label>
{{ field.label }}
</template>
<e-textarea
v-model="form[field.name]"
:name="field.name"
size="small"
#input="onInput($event, field.name)"
></e-textarea>
</e-form-group>
</div>
</template>
<script>
export default {
name: 'SettingsViewFields',
props: {
fields: {
type: Array,
default: () => [],
},
},
data: () => ({
form: [],
}),
};
</script>
I want that reactive data for input calls from field.name that the reactive data will be form: {question: '', button: ''} But the problem I have to set correct value for input, but if I set field.name the value will be not correct because for first input it's value: '123'.

You can't Change the data passed by the parent component directly, when you receive the prop data from parent that you want update, you can make a copy of this,eg
computed: {
fieldsCopy: function () {
return this.fields
},
}
and use fieldsCopy in your template, that may work.
if you also want to pass the updated data to parent , use emit.

Related

How do you push an object into another object when the data within it gets changed?

I have a very large array of objects containing various errors logs. There are 1015 objects in total. At the moment I am saving the entire array every time I make a small change to a value in one of the objects. This leads to timeout errors because it takes too long to go through the whole array.
So instead I would like to figure out how I can change it so that the program ONLY saves an object if that object has been changed on the frontend.
So if I have 1015 objects and I only change something in object no. 2, then only object no. 2 should be saved on submit.
I was thinking, maybe it would be possible to first let the program look for any changes. Then IF a change has occured it will move that particular object to a new (empty) object, which I can then submit.
So, in my code example, I would like to have this function implemented on the computed property "Fields" which has the key "done". This contains a checkbox that sets the value error.done to true or false. So I would like for the program to check if this specific value has changed. If it has changed from true to false or vice versa I would like to send this object to a new object.
eg. if errors.done is set from true to false, then move the changed object to a new object called changedValue.
<template>
<b-container>
<b-card class="mt-4">
<h5>{{ $t('events') }}</h5>
<b-table
:items="errors"
:fields="fields"
:per-page="[10, 25, 50]"
selectable
:select-mode="'single'"
#row-selected="onRowSelected"
#row-clicked="showModal"
sort-desc
/>
</b-card>
<error-log-entry-modal ref="errorLogEntryModal" :selected-error-log="selectedRows"/>
<button #click="submit">Submit</button>
</b-container>
</template>
<script>
import {errorService} from '#/services/error';
import ErrorLogEntryModal from '#/components/error-log/ErrorLogEntryModal';
import moment from 'moment';
export default {
components: {
ErrorLogEntryModal,
},
props: {
ownerId: String
},
data() {
return {
errors: null,
selectedRows: []
};
},
computed: {
fields() {
return [
{
key: 'done',
label: '',
thStyle: 'width: 1%',
template: {
type: 'checkbox',
includeCheckAllCheckbox: true,
}
},
{
key: 'priority',
label: this.$t('errorLogs.priority'),
sortable: true,
},
{
key: 'creationDateTime',
label: this.$t('creationDateTime'),
formatter: date => moment(date).locale(this.$i18n.locale).format('L'),
sortable: true,
},
{
key: 'stackTraceShort',
label: this.$t('errorLogs.stackTrace'),
sortable: true,
},
{
key: 'errorMessage',
label: this.$t('message'),
sortable: true
},
]
},
},
methods: {
load(){
errorService.getErrorLogs().then(result => {
result.data.forEach(log => log.stackTraceShort = log.stackTrace.substring(0,30));
this.errors = result.data
})
},
submit(){
return errorService.setStatusOnErrorEntryLog(this.errors).then( result => {
console.log(result)
})
},
onRowSelected(fields){
this.selectedRows = fields
},
showModal(){
if (this.selectedRows) {
this.$refs.errorLogEntryModal.show()
}
},
},
created() {
this.load()
},
};
</script>
If I have understood correctly the selected rows correspond to errors.done ? In this case you can just edit the onRowSelected method like this :
onRowSelected(fields){
this.selectedRows.push(fields)
},
Then replace this.errors by this.selectedRows in you're submit method ?

datatable vueJS don´t show data

I´m trayin integrate datatable in my component vue. For this i´m using this library:
https://jamesdordoy.github.io/
i´m install in my proyect, i has configured it, created my component and include in my view, but returned me this message:
Invalid prop: type check failed for prop "data". Expected Object, got Array
my component it´s:
<template>
<div>
<div class="row justify-content-center w-100">
<data-table :data="data" :columns="columns" #on-table-props-changed="reloadTable"></data-table>
</div>
</div>
</template>
<script>
export default {
data() {
return {
url: "/admin/vue/getAllUsers",
data: {},
tableProps: {
search: '',
length: 10,
column: 'id',
dir: 'asc'
},
columns: [
{
label: 'ID',
name: 'id',
orderable: true,
},
{
label: 'Name',
name: 'name',
orderable: true,
},
{
label: 'Email',
name: 'email',
orderable: true,
},
]
}
},
created() {
this.cargar(this.url);
},
methods:{
cargar(url = this.url, options = this.tableProps){
axios.get(url, { params: options })
.then((response) => {
this.data = response.data;
})
.catch((error) => console.error(error));
},
reloadTable(tableProps) {
this.cargar(this.url, tableProps);
}
},
}
</script>
i was trayed with response.data[0] the error disappear but my table it´s empty, i don´t know that i´m doing wrong.
In my controller i have this:
return User::all();
i´m working with laravel 8
thanks for help
you should pass props :items = "data" instead of :data = "data"

Array of Objects Data wont bind to Vuetify Data Table?

I have a Vuetify data table which takes the headers as an array of objects returned in the component and the data (:items) is bound to an array also returned in the component. This array is populated with Firestore data which is there, because I can console.log it.
The issue is that the data table is empty, and contains no data in the body at all.
Could this be caused because my items array contains more data points then I have headers in my table?
Vuetify Component
<template>
<v-card>
<v-card-title>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="items"
:search="search"
></v-data-table>
</v-card>
</template>
Component Script
<script>
/* eslint-disable */
import firestore from '/firebase.js';
export default {
data() {
return {
search: '',
items: [],
headers: [
{
text: 'ID',
align: 'start',
sortable: true,
value: 'name',
},
{ text: 'Date Created', value: 'Date Created' },
{ text: 'Date Finished', value: 'Date Finished' }
],
show: false,
};
},
name: "Home",
methods: {
getData() {
firestore.collection("itemStore")
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
var itemData = doc.data();
this.items.push({
id: itemData.incId,
dateCreated: itemData.dateCreated,
dateFinished: itemData.dateFinished,
email: itemData.email
});
console.log(this.items);
});
});
}
},
mounted() {
this.getData();
}
};
</script>
The value attribute of your headers collection has to correspond with the keys of your items. So in your case it should look like this:
headers: [
{
text: 'ID',
align: 'start',
sortable: true,
value: 'id',
},
{
text: 'Date Created',
value: 'dateCreated'
},
{
text: 'Date Finished',
value: 'dateFinished'
}
]

Reusable Vue component props passing

I'm trying to reuse the searchselect multiple times in the same vue file:
<SearchSelect :options="item in brandList"></SearchSelect>
<SearchSelect :options="item in modelTypes"></SearchSelect>
brandList: [
{ value: "A", text: "A" },
{ value: "B", text: "B" },
{ value: "C", text: "C" },
{ value: "D", text: "D" }
],
In my searchselect.vue i'm writing as:
<template>
<div>
<!-- object value -->
<model-select
:options="options"
v-model="item"
placeholder="select item"
></model-select>
</div>
</template>
export default {
props: ["itemOption"],
data() {
return {
options: [],
item: {
value: "",
text: ""
}
};
},
Can someone guide me what i did wrong on passing values from my vue.file data?
From a first glance, it looks like you are using the wrong name for your prop.
In SearchSelect, define the prop as follows.
export default {
props: {
options: Array
},
data: () => ({
item: { value: '', text: '' }
}),
}
The name of the prop is what you'll use to bind brandList and modelTypes to the component when you call it as:
<SearchSelect :options="item in brandList"></SearchSelect>
Note that options matches the name of the prop in the component above

Adding functionality to Vuetify component, mass pass in props

I want to be able to send props to a Vuetify component without needing to assign each one within my component, is there a way I can just mass pass in all of the props?
Below is what i'm currently doing, however there's a lot of prop'.
I have attempted to simply extend the VSelect component, however this returns multiple errors which don't seem simple to fix!
<template>
<v-flex xs12 sm6>
<v-select v-model="selected" :items="data"
:label="label"
:multiple="multiple"
:chips="chips"
:hint="hint"
:persistent-hint="persistentHint"
:counter="counter"
:dark="dark"
></v-select>
</v-flex>
</template>
<script>
export default {
props: {
label: {
default: false,
type: String|Boolean
},
multiple: {
default: true,
type: Boolean
},
chips: {
default: true,
type: Boolean
},
hint: {
default: '',
type: String|Boolean
},
persistentHint: {
default: this.hint !== '' || this.hint !== false,
type: String|Boolean
},
counter: {
default: false,
type: Number|Boolean
},
dark: {
default: false,
type: Boolean
},
},
data: function() {
return {
selected: [ ],
data: [
'test', 'test2', 'test3'
]
}
}
}
</script>
You can pass props as an object:
<v-select
v-model="selected"
:items="data"
v-bind="$props"
></v-select>
[ https://v2.vuejs.org/v2/guide/components-props.html#Passing-the-Properties-of-an-Object ]