Edit selected rows in vuejs - vue.js

editItem(){
if(this.selected.length!=1) {
alert("Choose only one row");
} else {
//what should i put in here?
}
}
Hi, I created a datatable with selectboxs for each row using vuejs.
I created a button that when clicked activates the method above, how can I make it that when just one row is selected a form is opened and you can edit the info in that row?
I made a form that when filled and a button "addItem" is clicked the data-table will insert the row with the info in the form.
I tried using v-edit-dialog but i just cant make it work...
here is the whole code:
<style>
table th + th { border-left:1px solid #dddddd; }
table td + td { border-left:1px solid #dddddd; }
</style>
<template>
<div id="consulta">
<v-container grid-list-xl fluid>
<v-layout row wrap>
<v-flex sm12>
<v-widget title="Testando">
<div slot="widget-content">
<v-container id="teste">
<v-layout row>
<v-flex xs4>
<v-subheader>EAN</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="ean"
label=""
color="primary"
id="ean"
mask="#.######.######"
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs4>
<v-subheader>Descrição</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="desc"
id="desc"
label=""
value=""
:rules="[(v) => v.length <= 50 || 'Max 50 characters']"
:counter="50"
single-line
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs4>
<v-subheader>Marca</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="marca"
label=""
color="primary"
id="marca"
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs4>
<v-subheader>Departamento</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="dep"
label=""
color="primary"
id="dep"
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs4>
<v-subheader>Categoria</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="categ"
label=""
color="primary"
id="categ"
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs4>
<v-subheader>Atributos</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="att"
label=""
color="primary"
id="att"
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs4>
<v-subheader>Loja</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="loja"
label=""
color="primary"
id="loja"
></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs4>
<v-subheader>URL</v-subheader>
</v-flex>
<v-flex xs8>
<v-text-field
name="url"
label=""
color="primary"
id="url"
></v-text-field>
</v-flex>
</v-layout>
<div>
<v-btn small color="primary" #click="addItem">Enviar</v-btn>
</div>
</v-container>
</div>
</v-widget>
</v-flex>
<v-flex sm12>
<h1>Tabela</h1>
</v-flex>
<v-flex lg12>
<v-toolbar card color="white">
<v-text-field
flat
solo
prepend-icon="search"
placeholder="Type something"
v-model="search"
hide-details
class="hidden-sm-and-down"
></v-text-field>
<v-btn icon>
<v-icon>filter_list</v-icon>
</v-btn>
</v-toolbar>
<v-divider></v-divider>
<v-card>
<v-card-text class="pa-0">
<v-data-table
:headers="headers"
:search="search"
:items="items"
item-key="ean"
class="elevation-1"
select-all
v-model="selected">
<template slot="items" slot-scope="props">
<td> <v-checkbox v-model="props.selected" primary hide-details></v-checkbox></td>
<td class="text-xs-center">{{ props.item.ean }}</td>
<td class="text-xs-center">{{ props.item.desc }}</td>
<td class="text-xs-center">{{ props.item.marca }}</td>
<td class="text-xs-center">{{ props.item.dep }}</td>
<td class="text-xs-center">{{ props.item.categ }}</td>
<td class="text-xs-center">{{ props.item.att }}</td>
<td class="text-xs-center">{{ props.item.loja }}</td>
<td class="text-xs-center">{{ props.item.url }}</td>
</template>
</v-data-table>
</v-card-text>
</v-card>
<div>
<v-btn color="red" #click="deleteItem">Delete</v-btn>
<v-btn color="orange" #click="editItem">Edit</v-btn>
</div>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
import API from '#/api';
import EChart from '#/components/chart/echart';
import MiniStatistic from '#/components/widgets/statistic/MiniStatistic';
import PostListCard from '#/components/widgets/card/PostListCard';
import ProfileCard from '#/components/widgets/card/ProfileCard';
import PostSingleCard from '#/components/widgets/card/PostSingleCard';
import WeatherCard from '#/components/widgets/card/WeatherCard';
import PlainTable from '#/components/widgets/list/PlainTable';
import PlainTableOrder from '#/components/widgets/list/PlainTableOrder';
import VWidget from '#/components/VWidget';
import Material from 'vuetify/es5/util/colors';
import VCircle from '#/components/circle/VCircle';
import BoxChart from '#/components/widgets/chart/BoxChart';
import ChatWindow from '#/components/chat/ChatWindow';
import CircleStatistic from '#/components/widgets/statistic/CircleStatistic';
import LinearStatistic from '#/components/widgets/statistic/LinearStatistic';
export default {
layout: 'dashboard',
components: {
VWidget,
MiniStatistic,
ChatWindow,
VCircle,
WeatherCard,
PostSingleCard,
PostListCard,
ProfileCard,
EChart,
BoxChart,
CircleStatistic,
LinearStatistic,
PlainTable,
PlainTableOrder
},
data() {
return{
search: '',
selected: [],
headers:[
{text:'EAN', value:'ean', sortable: true, align:"center"},
{text:'Descrição', value:'desc', sortable: true, align:"center"},
{text:'Marca', value:'marca', sortable: true, align:"center"},
{text:'Departamento', value:'dep', sortable: true, align:"center"},
{text:'Categoria', value:'categ', sortable: true, align:"center"},
{text:'Atributos', value:'att', sortable: true, align:"center"},
{text:'Loja', value:'loja', sortable: true, align:"center"},
{text:'URL', value:'url', sortable: true, align:"center"},
],
items:[{
ean: '9234858583',
desc: 'Item teste',
marca: 'Danone',
dep: 'Comida?',
categ: 'Laticinio',
att: 'Yogurt',
loja: 'Mercadinho',
url: 'www.mercadinho.fakeaddress.com',
}],
}
},
methods: {
addItem(){
if(document.querySelector("#ean").value!=""&&
document.querySelector("#desc").value!=""&&
document.querySelector("#marca").value!=""&&
document.querySelector("#dep").value!=""&&
document.querySelector("#categ").value!=""&&
document.querySelector("#att").value!=""&&
document.querySelector("#loja").value!=""&&
document.querySelector("#url").value!=""){
let registro = {
"ean": document.querySelector("#ean").value,
"desc": document.querySelector("#desc").value,
"marca":document.querySelector("#marca").value,
"dep": document.querySelector("#dep").value,
"categ": document.querySelector("#categ").value,
"att": document.querySelector("#att").value,
"loja": document.querySelector("#loja").value,
"url": document.querySelector("#url").value,
};
this.insert(registro);
this.items.push(registro)
}
else{
alert("Um ou mais campos não foram preenchidos!");
}
},
editItem(){
if(this.selected.length){
alert("Select just one row")
}
else{
//show form to edit the info
}
},
deleteItem(){
if(confirm("Deseja deletar tais fileiras?")){
for(var i = 0; i < this.selected.length; i++){
const index = this.items.indexOf(this.selected[i]);
this.items.splice(index, 1);
}
}
}
}
}
</script>

Since you're using Vuetify as your Material Design Framework you could use the Dialog Component. You can find many Example in the official documentation: https://vuetifyjs.com/en/components/dialogs#form

Related

add ingredient to shopping List

I have a project to add an ingredient in a recipe to "Shopping List".
And in this picture there are several ingredients at the bottom "sugar".
When I click on the plus sign I want to add the ingredient to the "shopping List".
How can I solve this problem?
In this file, you create an ingredient with this ingredient's data such as its name and quantity.
CreateIngredient:
<template>
<v-app>
<v-container>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<h2 class="btn-style">Add Ingredient</h2>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<form #submit.prevent="onAddIngredient">
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field name="id" label="Id" id="id" v-model="id" color="#43A047" required>
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field name="name" label="Name" id="name" v-model="Name" color="#43A047" required>
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field name="ingredientsQuantity" label="Ingredients Quantity" id="ingredientsQuantity" v-model="Quantity" color="#43A047" multi-line required>
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<v-btn class="green darken-1 color" type="submit">
Add
</v-btn>
</v-flex>
</v-layout>
</form>
</v-flex>
</v-layout>
</v-container>
</v-app>
</template>
<script>
export default {
data() {
return {
id: "",
Name: "",
Quantity: "",
};
},
computed: {
formIsValid() {
return (
this.id !== "" &&
this.Name !== "" &&
this.Quantity !== ""
);
}
},
methods: {
onAddIngredient() {
if (!this.formIsValid) {
return;
}
const ingredientData = {
id: this.id,
Name: this.Name,
Quantity: this.Quantity
};
this.$store.commit("createIngredients", ingredientData);
const stringifiedData = JSON.stringify(ingredientData);
// console.log("S: ", stringifiedData);
localStorage.setItem("ingredient", stringifiedData);
console.log("We got : ", JSON.parse(localStorage.getItem("ingredient")));
}
},
};
</script>
<style scoped>
.btn-style {
color: #43a047;
}
.color {
color: #fafafa;
}
</style>
And this file that displays all the ingredients
shoppingList:
<template>
<div>
<v-container class="mb-30">
<v-flex class="floating-right">
<v-btn large router to="/CreateNewIngrediets" class="green darken-1 btn-style margine mr-50">
<v-icon class="green darken-1 btn-style">mdi-plus</v-icon>
</v-btn>
</v-flex>
<v-container>
<v-layout row wrap v-for="ingredient in ingredients" :key="ingredient.id" class="mb-3 mt-4">
<v-flex xs6 sm8 md4 offset-sm1 offset-md2>
<v-card class="grey lighten-4 pl-3 ">
<v-container fluid>
<v-layout row class="pl-14">
<v-flex xs7 sm8 md9>
<v-card-title primary-title>
<v-flex xs7 sm8 md9>
<div>
{{ ingredient.Name }}
</div>
</v-flex>
<v-flex xs7 sm8 md9>
<div>
{{ ingredient.Quantity }}
</div>
</v-flex>
<v-flex xs5 sm4 md2>
<v-btn class="deleteColorIcon">
<v-icon left class=" pl-4" #click="
$store.commit('delete_ingredient', ingredient.id)
">
mdi-delete
</v-icon>
<!-- </v-btn> -->
</v-btn>
</v-flex>
</v-card-title>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-flex>
</v-layout>
</v-container>
</v-container>
</div>
</template>
<script>
export default {
computed: {
Recipes() {
return this.$store.getters.loadedRecipes;
},
ingredients() {
return this.$store.getters.loadedingredients;
}
}
};
</script>
<style scoped>
.color {
color: #43a047;
}
.deleteColorIcon {
color: #e53935;
}
.btn-style {
color: aliceblue;
}
</style>
And this file that displays the recipe as the image above, and through it, all the recipe elements, including the ingredients, are displayed.
Recipe:
<template>
<v-container>
<v-layout row wrap>
<v-flex x12>
<v-card>
<!-- <v-card-title> -->
<v-card-text>
<h4 class="btn-style mt-4 mb-4 font">
{{ recipe.title }}
</h4>
<v-img height="530px" :src="recipe.imageUrl" class="mb-4"></v-img>
<div class="btn-style mb-6">
{{ recipe.description }}
</div>
<div v-for="ing in recipe.ingredients" :key="ing.id">
{{ ing.Name }} {{ ing.Quantity }}
<v-btn class="green darken-1 color mb-5 ml-4 mr-4 pl-50">
<v-icon class="green darken-1 btn-style">mdi-plus</v-icon>
</v-btn>
</div>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<!-- <v-flex xs5 sm4 md2> -->
<v-btn class=" mb-4 mr-4">
<v-icon left class=" pl-4 ">
mdi-pen
</v-icon>
<!-- </v-btn> -->
</v-btn>
<!-- </v-flex> -->
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import {
mapGetters
}
from "vuex";
export default {
props: ["id"],
computed: {
recipe() {
const loadedRecipe = this.$store.getters.loadedRecipe(this.id);
console.log("We loaded a recipe with value : ", loadedRecipe);
return loadedRecipe;
},
ingredient() {
return this.$store.getters.loadedingredient(this.id);
}
},
methods: {
}
};
</script>
<style scoped>
.btn-style {
color: #43a047;
}
.color {
color: #fafafa;
}
.deleteColorIcon {
color: #e53935;
}
.font {
font-size: 30px;
}
</style>
You can put a on click observer un your button, define a function that would execute in such case and pass it the object you want to store like so:
<div v-for="ing in recipe.ingredients" :key="ing.id">
{{ ing.Name }} {{ ing.Quantity }}
<v-btn class="green darken-1 color mb-5 ml-4 mr-4 pl-50" #click="addToShoppingList(ing)">
<v-icon class="green darken-1 btn-style">mdi-plus</v-icon>
</v-btn>
</div>
Then in vuex, store it in the state using an action and a mutator:
export default new Vuex.Store({
state: {
shoppingList: []
},
getters: {
getShoppingList(state) { return state.shoppingList }
},
mutations: {
ADD_ITEM_TO_SHOPPING_LIST(state, ingParam) {
state.shoppingList.push(ingParam);
}
}
,
actions: {
addItemToShoppingList({commit}, ingParam) {
commit('ADD_ITEM_TO_SHOPPING_LIST', ingParam);
}
}
And last thing in your methods like so:
export default {
methods: {
addToShoppingList(ingParam) {
this.$store.dispatch('addItemToShoppingList', ingParam);
}
}
}
Hope it helps ;)

create alert in Recipe Component

This is a project for running a site that displays recipes and performs several operations such as creating a site, but I encountered this problem.
I have this file to create a recipe where I enter the recipe data, but how can I create an alert on this page says that creating a recipe succeeded.
How can I solve the Problem?
The data is in this file.
createRecipe.vue:
<template>
<v-app>
<v-container>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<h2 class="btn-style">Create Recipe</h2>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<form #submit.prevent="onCreateRecipe">
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field
name="id"
label="Id"
id="id"
v-model="id"
color="#43A047"
required
>
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field
name="title"
label="Title"
id="title"
v-model="title"
color="#43A047"
required
>
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field
name="imageUrl"
label="ImageUrl"
id="imageUrl"
v-model="imageUrl"
color="#43A047"
required
>
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<img :src="imageUrl" height="300px">
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field
name="description"
label="Description"
id="description"
v-model="description"
color="#43A047"
multi-line
required
>
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field
name="ingredientsName"
label="IngredientsName"
id="ingredientsName"
v-model="ingredientsName"
color="#43A047"
multi-line
required
>
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-text-field
name="ingredientsQuantity"
label="IngredientsQuantity"
id="ingredientsQuantity"
v-model="ingredientsQuantity"
color="#43A047"
multi-line
required
>
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<v-btn
class="green darken-1 color"
:disabled="!formIsValid"
type="submit"
>
Create Recipe
</v-btn>
</v-flex>
</v-layout>
</form>
</v-flex>
</v-layout>
</v-container>
</v-app>
</template>
<script>
export default {
data() {
return {
id:"",
title: "",
imageUrl: "",
description: "",
ingredientsName: "",
ingredientsQuantity: "",
};
},
computed: {
formIsValid() {
return (
this.id !== ""&&
this.title !== "" &&
this.description !== "" &&
this.imageUrl !== "" &&
this.ingredientsName !== ""&&
this.ingredientsQuantity !== ""
);
}
},
methods: {
onCreateRecipe() {
if (!this.formIsValid) {
return;
}
const recipeData = {
id:this.id,
title: this.title,
description: this.description,
imageUrl: this.imageUrl,
ingredientsName: this.ingredientsName,
ingredientsQuantity: this.ingredientsQuantity
};
// Here we call the setter to put the Data inside it
this.$store.commit('createRecipe', recipeData)
const stringifiedData = JSON.stringify(recipeData);
// console.log("S: ", stringifiedData);
localStorage.setItem("recipe", stringifiedData);
console.log("We got : ", JSON.parse(localStorage.getItem("recipe")));
},
}
};
</script>
<style scoped>
.btn-style {
color: #43a047;
}
.color {
color: #fafafa;
}
</style>
You need to use async action not mutation you can not use async operations with mutations. It should look like this:
this.$store.dispatch('createRecipe', recipeData).then(() => //alert('STH') or whatever you want to do after you add recipe)

How to fix the "this.$refs.[ref_name].save is not a function" in a "v-for" created component?

I'm working on a table list with some crud actions. When I click on the edit icon, I will open a dialog box that includes 3 "v-tabs-items" through a "v-for".
In the last v-tab i have an v-time-picker input in a menu, and use the structure of the Vuetify documentation.
<template>
<v-flex>
<v-data-table>
<!-- some data -->
</v-data-table>
<v-dialog
v-model="dialog"
>
<v-card>
<v-flex>
<v-toolbar color="secondary" light tabs>
<v-card-title>
<span class="headline">{{ formTitle }}</span>
</v-card-title>
<v-spacer />
<template v-slot:extension>
<v-tabs
v-model="tab"
color="secondary"
align-with-title
>
<v-tabs-slider color="accent" />
<v-tab v-for="i in items" :key="i">
{{ i }}
</v-tab>
</v-tabs>
</template>
</v-toolbar>
<v-tabs-items v-model="tab">
<v-tab-item v-for="i in items" :key="i">
<v-card flat>
<v-card-text v-if="i === 'Ad'" class="pa-0">
<!-- Some Content -->
</v-card-text>
<v-card-text v-if="i === 'Content'" class="pa-0">
<!-- Some Content -->
</v-card-text>
<v-card-text v-if="i === 'Target'" class="pa-0">
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs12 sm6 md6>
<v-menu
ref="time_picker"
v-model="dailyTimeMenu1"
:close-on-content-click="false"
:nudge-right="-15"
:return-value.sync="editedItem.daily_time_from"
lazy
transition="scale-transition"
offset-y
full-width
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="editedItem.daily_time_from"
label="Time From"
prepend-icon="access_time"
readonly
outline
class="mr-2"
v-on="on"
/>
</template>
<v-time-picker
v-if="dailyTimeMenu1"
v-model="editedItem.daily_time_from"
full-width
#click:minute="$refs.time_picker.save(editedItem.daily_time_from)"
/>
</v-menu>
</v-flex>
<v-flex xs12 sm6 md6>
<v-menu
ref="time_picker"
v-model="dailyTimeMenu2"
:close-on-content-click="false"
:nudge-right="-15"
:return-value.sync="editedItem.daily_time_to"
lazy
transition="scale-transition"
offset-y
full-width
disabled
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="editedItem.daily_time_to"
label="Time to"
prepend-icon="access_time"
readonly
outline
v-on="on"
/>
</template>
<v-time-picker
v-if="dailyTimeMenu2"
v-model="editedItem.daily_time_to"
full-width
#click:minute="$refs.time_picker.save(editedItem.daily_time_to)
/>
</v-menu>
</v-flex>
</v-layout>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn color="blue darken-1" flat #click="close">
Cancel
</v-btn>
<v-btn color="blue darken-1" flat #click="saved">
Save
</v-btn>
</v-card-actions>
</v-card>
</v-tab-item>
</v-tabs-items>
</v-flex>
</v-card>
</v-dialog>
</v-flex></template>
...
and the script and Data object is.
<script>
export default {
data: vm => ({
dailyTimeMenu1: false,
dailyTimeMenu2: false,
items: [
'Ad', 'Content', 'Target'
],
tab: null,
dialog: false,
editedItem: {
daily_time_from: null,
daily_time_to: null,
}
})
}
The problem happens when I want to save the time when I pick the minutes.
I receive this error:
this.$refs.time_picker.save is not a function
Can you please explain to me what the problem is and how I can fix it?
Since you use ref="time_picker" in a v-for, this.$refs.time_picker will actually be an array. So you will need to keep track of the index in
<v-tab-item v-for="(i, idx) in items" :key="i">
and use idx in your all of your references to $refs.time_picker, like:
#click:minute="$refs.time_picker[idx].save(editedItem.daily_time_to)
EDIT: You also need to rename the second v-menu with the ref time_picker to something else, as it is now ambiguous which element you are referring to.

v-for in vue update all object in array although the key has been determined

this my code :
<v-container grid-list-md fluid-fix>
<div v-for="(data ,c) in chapter.data" :key="c" class="my-3" style="border: 1px solid;">
<v-layout row wrap px-3>
<v-flex xs12 sm1>
<v-text-field v-model="data.num" label="Chapter"></v-text-field>
</v-flex>
<v-flex xs12 sm3>
<v-text-field v-model="data.name" label="name"></v-text-field>
</v-flex>
<v-flex xs12 sm8 d-flex>
<v-text-field v-model="data.description" label="short info" style="width: 100%;"></v-text-field>
<div>
<v-btn class="d-inline-flex servers--btn" color="success" #click="addServer(c)">add server</v-btn>
</div>
</v-flex>
</v-layout>
<v-container grid-list-md fluid-fix>
<v-layout wrap v-for="(server ,s) in data.servers" :key="s">
<v-flex sm12>
<div class="d-inline-flex">
<v-autocomplete
:items="data.serverlist"
v-model="server.server_id"
#input="serverChange(data)"
label="Server"
></v-autocomplete>
</div>
<div class="d-inline-flex text-xs-right pr-1">
<v-btn color="orange" class="white--text servers--btn" #click="demo_edit(c,s,server.links)">demo and Edit</v-btn>
</div>
<div class="d-inline-flex text-xs-right pr-1" style="float: right;">
<v-btn color="red" class="white--text servers--btn" #click="delSvOnChap(c,s)">Delete Server</v-btn>
</div>
</v-flex>
<v-flex sm12>
<v-textarea
v-model="server.links"
label="box image"
></v-textarea>
</v-flex>
</v-layout>
</v-container>
serverChange(data){
data.serverlist.forEach(obj => {
if(_.find(data.servers,{server_id: obj.value})){
obj.disabled = true
}else{
obj.disabled = false
}
});
},
serverChange is in methods
i want update disabled in the key has been determined , but it's update all object in array
when I log serverChange function i just see one object return and that's what I'm looking forward to but when i set disabled for this object , vue update all object in array
I need a solution for this problem .

Unknown custom element: <x-flex> - did you register the component correctly? For recursive components, make sure to provide the "name" option

How Do I resolve this. I am getting the error Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option. This error is being printed on the console as I run the app. When it does this , the nothing is displayed on on the views its just blank.
<template>
<v-container id="dashboard" fluid grid-list-lg class="mx- pa-7">
<v-layout row wrap>
<v-flex md3 sm6 xs12>
<v-card class="cyan darken-3" l light>
<v-container fluid grid-list-sm light>
<v-layout class="mt-0 mb-0" row wrap>
<v-flex d-flex xs3>
<v-icon class="mx-0" x-large light>beenhere</v-icon>
</v-flex>
<v-flex d-flex xs9 >
<v-layout class="mt-2 mb-0 pa-0" row wrap>
<x-flex d-flex xs12>
<div class="silver--text subheading">Income Revenue</div>
</x-flex>
<v-flex d-flex xs12>
<div class="silver--text display-1">{{totalUsers}}</div>
<v-btn outline class="darkgrey--text darken-1" right flat small>More</v-btn>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-flex>
<v-flex md3 sm6 xs12>
<v-card class="blue-grey darken-1">
<v-container fluid grid-list-sm light>
<v-layout class="mt-0 mb-0" row wrap>
<v-flex d-flex xs3>
<v-icon class="mx-0" x-large light>beenhere</v-icon>
</v-flex>
<v-flex d-flex xs9 >
<v-layout class="mt-2 mb-0 pa-0" row wrap>
<x-flex d-flex xs12>
<div class="silver--text subheading">Today's Revenue</div>
</x-flex>
<v-flex d-flex xs12>
<div class="silver--text display-1">{{totalAmount}}</div>
<v-btn outline class="darkgrey--text darken-1" right flat small>More</v-btn>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-flex>
<v-flex md3 sm6 xs12>
<v-card class="pink lighten-4">
<v-container fluid grid-list-sm light>
<v-layout class="mt-0 mb-0" row wrap>
<v-flex d-flex xs3>
<v-icon class="mx-0" x-large light>beenhere</v-icon>
</v-flex>
<v-flex d-flex xs9 >
<v-layout class="mt-2 mb-0 pa-0" row wrap>
<x-flex d-flex xs12>
<div class="silver--text subheading">Yesterday's Revenue</div>
</x-flex>
<v-flex d-flex xs12>
<div class="silver--text display-1">{{totalUsersThis}}</div>
<v-btn outline class="darkgrey--text darken-1" right flat small>More</v-btn>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-flex>
<v-flex md3 sm6 xs12>
<v-card class="blue-grey darken-1">
<v-container fluid grid-list-sm light>
<v-layout class="mt-0 mb-0" row wrap>
<v-flex d-flex xs3>
<v-icon class="mx-0" x-large light>beenhere</v-icon>
</v-flex>
<v-flex d-flex xs9 >
<v-layout class="mt-2 mb-0 pa-0" row wrap>
<x-flex d-flex xs12>
<div class="silver--text subheading">This Week's Revenue</div>
</x-flex>
<v-flex d-flex xs12>
<div class="silver--text display-1">{{totalAmountThis}}</div>
<v-btn outline class="darkgrey--text darken-1" right flat small>More</v-btn>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-flex>
</v-layout>
<v-layout class="pt-1" row wrap>
<v-flex md4 xs12>
<v-card light>
<doughnut></doughnut>
</v-card>
</v-flex>
<v-flex md4 xs12>
<v-card light>
<bar></bar>
</v-card>
</v-flex>
<v-flex md4 xs12>
<v-card light class="Chart">
<line-chart></line-chart>
</v-card>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs7>
<v-card>
<v-card-title>
Recent Transactions
<v-spacer/> <v-spacer/>
<v-text-field name="product" label="Search" light v-model="searchTransaction"></v-text-field>
</v-card-title>
<v-data-table v-bind:headers="headers" v-bind:items="items" v-bind:search="search"
v-bind:pagination.sync="pagination" hide-actions
class="elevation-1">
<template slot="items" slot-scope="props" class="body-2" >
<td class="body-2" >{{ props.item.account_from }}</td>
<td class="text-xs-left">{{ props.item.amount }}</td>
<td class="text-xs-left">{{ props.item.transaction_code}}</td>
<td class="text-xs-left">{{ props.item.payment_mode}}</td>
<td class="text-xs-left">{{ props.item.ref}}</td>
<td class="text-xs-left">{{ props.item.status}}
</td>
<td class="text-xs-left">{{ props.item.date}}</td>
<!-- <td class="text-xs-left">{{ props.item.quantity}}</td>
<td class="text-xs-left"><img :src='getImageURL(props.item.Product.phone_number)' height="90dp" width="90dp"/></td>
<td class="text-xs-left">
<v-btn fab small dark class="teal" #click.native="edit()">
<v-icon>edit</v-icon>
</v-btn>
<v-btn fab small class="cyan" #click.native="remove(props.item)">
<v-icon>delete</v-icon>
</v-btn>
</td>-->
</template>
</v-data-table>
<div class="text-xs-center pt-2">
<v-pagination v-model="pagination.page" :length="pages" circle></v-pagination>
</div>
</v-card>
</v-flex>
<v-flex xs5>
<v-card>
<v-card-title>
Merchants
<v-spacer/> <v-spacer/>
<v-text-field name="product" label="Search" light v-model="productSearch"></v-text-field>
</v-card-title>
<v-data-table v-bind:headers="headers2" v-bind:items="businesses" v-bind:search="search"
v-bind:pagination.sync="pagination2" hide-actions
class="elevation-1"
:loading="false">
<v-progress-linear slot="progress" color="blue" indeterminate></v-progress-linear>
<template slot="items" slot-scope="props" class="body-2" >
<td class="body-2" >{{ props.item.business_name }}</td>
<td class="text-xs-left">{{ props.item.short_code }}</td>
<td class="text-xs-left">{{ props.item.sender_id}}</td>
<!--<td class="text-xs-left">{{ props.item.payment_mode}}</td>
<td class="text-xs-left">KES {{ props.item.transaction_ref}}</td>
<td class="text-xs-left">KES {{ props.item.date}}</td>-->
<!-- <td class="text-xs-left">{{ props.item.quantity}}</td>
<td class="text-xs-left"><img :src='getImageURL(props.item.Product.phone_number)' height="90dp" width="90dp"/></td>
<td class="text-xs-left">
<v-btn fab small dark class="teal" #click.native="edit()">
<v-icon>edit</v-icon>
</v-btn>
<v-btn fab small class="cyan" #click.native="remove(props.item)">
<v-icon>delete</v-icon>
</v-btn>
</td>-->
</template>
</v-data-table>
<div class="text-xs-center pt-2">
<v-pagination v-model="pagination2.page" :length="pages2" circle></v-pagination>
</div>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import Bar from "../components/chart/Bar";
import Doughnut from "../components/chart/Doughnut";
import LineChart from "../components/chart/LineChart";
import { execute } from '../api'
export default {
name: "Dashboard",
components: {
Bar,
Doughnut,
LineChart
},
data () {
return {
searchTransaction:'',
items:[],
businesses:[],
totalUsers:'',
totalAmount:'',
totalUsersThis:'',
totalAmountThis:'',
search: '',
pagination: [],
pagination2: [],
productSearch:'',
headers: [
{
text: 'Phone Number',
left: true,
sortable: false,
value: 'phone_number'
},
{ text: 'Amount', value: 'amount' , sortable: false,},
{ text: 'Transaction Code', value: 'transaction_code' , sortable: false,},
{ text: 'Payment Mode', value: 'payment_mode' , sortable: false},
{ text: 'Transaction ref', value: 'transaction_ref' , sortable: false},
{ text: 'Status', value: 'status' , sortable: false},
{ text: 'date', value: 'date' , sortable: false}
], headers2: [
{
text: 'Business',
left: true,
sortable: false,
value: 'business'
},
{ text: 'ShortCode', value: 'short_code' , sortable: false,},
{ text: 'Sender ID', value: 'sender_id' , sortable: false,},
]
};
},
watch: {
searchTransaction: function() {
this.getTransactions();
}
},
methods: {
getCustomers () {
const data = new FormData()
data.append('TransactionType', 'getDashboardData')
execute(data).then((res) => {
this.totalUsers= new Intl.NumberFormat().format(res.data.data.IncomeRevenue)
this.totalAmount= new Intl.NumberFormat().format(res.data.data.TodayRevenue)
this.totalUsersThis= new Intl.NumberFormat().format(res.data.data.YesterdayRevenue)
this.totalAmountThis= new Intl.NumberFormat().format(res.data.data.ThisWeekRevenue)
}).catch((e) => {
// TODO
})
},
getTransactions () {
const data = new FormData()
data.append('TransactionType', 'getRecentTransactions')
data.append('keyword',this.searchTransaction)
execute(data).then((res) => {
this.items = res.data.data
}).catch((e) => {
// TODO
})
}, getBusinesses () {
const data = new FormData()
data.append('TransactionType', 'getBusinesses')
execute(data).then((res) => {
this.businesses = res.data.data
}).catch((e) => {
// TODO
})
}
},
computed: {
pages () {
return this.pagination && this.pagination.rowsPerPage ? Math.ceil(this.pagination.totalItems / this.pagination.rowsPerPage) : 0
},
pages2 () {
return this.pagination2 && this.pagination2.rowsPerPage ? Math.ceil(this.pagination2.totalItems / this.pagination2.rowsPerPage) : 0
}
},
mounted () {
this.getCustomers()
this.getTransactions()
this.getBusinesses()
}
};
</script>
<!--<style scoped>
#dashboard .flex {
margin-bottom: 2px;
}
</style>-->
Since you're using lots of <v-flex> elements in your code, my guess is you just made a typo and accidentally created a <x-flex> element. Just fix the typo (change all the x-flex to v-flex in your code) and it will work