How to push items into nested array in Vuetify treeview component - javascript

I am attempting to setup a Vuetify treeview component to enable the pushing of input into the nested array of existing items. So far, I have been able to set up the component to enable the pushing of input into the nested array of a dynamically added item. However, I want to push new input into the nested array of the existing 'applications' item, instead of creating an entirely new item. How can I achieve this? See my code below. Thanks!
<template>
<v-app data-app>
<v-app-bar app flat>
<v-text-field v-model="newItem" placeholder="add new item"></v-text-field>
<div class="flex-grow-1"></div>
<v-btn color="success" #click="addItem()">
Add Item
</v-btn>
</v-app-bar>
<v-treeview :items="items"></v-treeview>
</v-app>
</template>
<script>
export default {
data: () => ({
newItem: null,
items: [
{
id: 1,
name: 'Applications :',
children: [
{ id: 2, name: 'Calendar : app' },
{ id: 3, name: 'Chrome : app' },
{ id: 4, name: 'Webstorm : app' },
],
},
],
}),
methods: {
addItem () {
this.items.push({
name: 'Applications :',
children: [
{ id: 5, name: this.newItem },
],
})
}
}
}
</script>

Related

computed filter function in array of names in JS

I created small piece of code to search from given array in search bar. As i unserstood it is better to use computed function over method but when I put function in it dosen't work and give me an error: Duplicate keys detected: '3'. This may cause an update. So how can I solve it?
My function:
data() {
return {
RMnames: [],
filteredNames: [
{ name: "Zales", category: "Jewelry", id: 1 },
{ name: "Lux", category: "Jewelry", id: 2 },
{ name: "Edited", category: "Jewelry", id: 3 },
{ name: "Editedsdsdxs", category: "Jewelry", id: 3 },
],
searchTerm: "",
Names: [],
};
},
computed: {
filteredFunction() {
this.Names = this.filteredNames.filter((n) => {
return n.name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
});
},
},
My template:
<v-col align-self="start">
<v-text-field
v-model="searchTerm"
placeholder="Search"
#input="filteredFunction"
></v-text-field>
<v-card v-for="item in filteredNames" :key="item.id">
<v-card-title>{{ item.name }}</v-card-title>
</v-card>

VueJs How to make dropdown component to accept different types of props

I want to create a dynamic dropdown component where the amount of dropdowns and their options would be dynamic based on the props provided.
I would like to call the dropdown component and pass an object with the names of individual selects. I want the number of select to be determined by the names provided.
selectNameUsers: { users: "Users", roles: "Roles" } - this should create two dropdowns with the name of users and roles. - THIS HAS BEEN DONE.
Now my question/issue. How can I pass the data for the options. My attempt kinda works but the data provided is:
a) duplicated across multiple selects
b) I had to hard code the v-for= for the data provided so the component is not truly dynamic.
Any ideas?
Code:
https://codesandbox.io/s/adoring-lewin-2pqlq?file=/src/components/parent.vue:0-1245
App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<parent />
</template>
<script>
import parent from "./components/parent.vue";
export default {
name: "App",
components: {
parent: parent,
},
};
</script>
parent.vue
<template>
<div class="first">
<custom-dropdown
title="Users Manager"
instructions="Assign Role to User"
:selectName="selectNameUsers"
:users="users"
:roles="roles"
>
</custom-dropdown>
</div>
<div class="second">
<custom-dropdown
title="Cars Manager"
instructions="Look at cars"
:selectName="selectNameCars"
:cars="cars"
>
</custom-dropdown>
</div>
</template>
<script>
import customDropdown from "./customDropdown.vue";
export default {
components: { customDropdown },
data() {
return {
selectNameUsers: { users: "Users", roles: "Roles" },
selectNameCars: { cars: "Cars" },
users: [
{ uid: 1, name: "Ade", role: "standard" },
{ uid: 2, name: "Bab", role: "admin" },
{ uid: 3, name: "Cad", role: "super_admin" },
],
roles: [
{ rid: 1, name: "standard" },
{ rid: 2, name: "admin" },
{ rid: 3, name: "super_admin" },
],
cars: [
{ cid: 1, type: "Audi", colour: "Red" },
{ cid: 2, type: "BMW", colour: "Black" },
],
};
},
};
</script>
customDropdown
<template>
<div>
<h1>{{ title }}</h1>
<select
v-for="(objectvalue, keyName, index) in selectName"
:key="index"
:name="keyName"
>
<option v-for="user in users" :key="user.uid" :value="user.uid">
{{ user.name }}
</option>
<option v-for="role in roles" :key="role.rid" :value="role.uid">
{{ role.name }}
</option>
</select>
<h2>{{ instructions }}</h2>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
},
instructions: {
type: String,
},
selectName: {
type: Object,
},
users: {
type: Object,
},
roles: {
type: Object,
},
},
data() {
return {};
},
};
</script>

Vuejs draggable sorted list

I'm using Vue.Draggable plugin to implement a draggable list. I'm passing a sorted computed property, like the following:
data(){
return {
paymentMethods: [
{ name: 'stripe', Dindex: 0, state: 2 },
{ name: 'paypal', Dindex: 1 , state: 1 },
{ name: '2checkout', Dindex: 2, state: 4 },
{ name: 'cod', Dindex: 3, state: 3 }
],
}
},
computed: {
payments() {
return _.sortBy(this.paymentMethods, 'state');
},
}
Draggable list:
<draggable :list="payments" class="payment-methods" tag="ul" #start="drag=true" #end="drag=false" #change="indexChanged">
<li v-for="(method, index) in payments" :key="index">
<!-- list data -->
</li>
</draggable>
The problem here is the draggable list never works because i'm forcing the list sorting (using lodash _.sortBy), the question is how i can sort inside a draggable list.
While it is a computed value the list will sorted again when you drag it. I think the best thing to do is sort it when mounted:(So only initially)
data() {
return {
payments: []
paymentMethods: [
{ name: 'stripe', Dindex: 0, state: 2 },
{ name: 'paypal', Dindex: 1 , state: 1 },
{ name: '2checkout', Dindex: 2, state: 4 },
{ name: 'cod', Dindex: 3, state: 3 }
],
}
}
mounted() {
payments = _.sortBy(this.paymentMethods, 'state');
}
I know this is kind of old but I've also tried Googling for a solution and couldn't find any. A few minutes later I came up with this:
// <template />
<draggable
class="drag-wrapper selected-cols"
v-bind="dragOptions"
...other props
#change="colChange"
>
<div v-for="(col, i) in availableColumns" :key="col.name + '-' + i">
<div class="drag-area">
{{ col.label }}
</div>
</div>
</draggable>
// <scripts />
methods: {
colChange(e) {
this.availableColumns.sort((a, b) =>
a.label.localeCompare(b.label));
},
},
So instead of using a computed for sorting, I just do the sorting in the #change listener since that is being called AFTER vuedraggable is done sorting.

How to access to item from HTML Node [Vue.js]

I have:
Vue app data:
data: function() {
return {
items: [
{id: 1, text: 'one', other_data: {}},
{id: 2, text: 'two', other_data: {}},
{id: 3, text: 'three', other_data: {}}
]
}
}
Template:
<div v-for="item in items" id="my_items">
<span>{{ item.text }}</span>
</div>
And i need to access from one item by external JS code like next:
let item_node = document.getElementById('my_items').children[1]; // get 2nd child node of #my_items
item_node.__vuedata__ // must be a 2nd item from items in Vue data. {id: 2, text: 'two'...
How to do like this?
Vue recommends to use ref over ID and classes for DOM references. We use ref as a replacement for id. Since it is used on top of the v-for directive, all child elements are now referenced as an array of the ref. So every span will now be hello[0] - hello[n] The mounted code outputs the item.text for first child as it uses 0.
I added a click listener, every time you click the element, the value of item is passed to the method. Here you can extract all values and do whatever manipulation you require. Hope this is what you are looking for.
<template>
<div id="app">
<div v-for="item in items" :key="item.id" ref='hello' #click="logItem(item)">
<span>{{ item.text }}</span>
</div>
</div>
</template>
<script>
export default {
name: "App",
data: function() {
return {
items: [
{id: 1, text: 'one', other_data: {}},
{id: 2, text: 'two', other_data: {}},
{id: 3, text: 'three', other_data: {}}
]
}
},
methods: {
logItem: (item) => console.log(item)
},
mounted: function() {
console.log(this.$refs.hello[0].innerText)
}
};
</script>

Multiple select Vue.js and computed property

I'm using Vue.js 2.0 and the Element UI library.
I want to use a multiple select to attribute some roles to my users.
The list of all roles available is received and assigned to availableRoles. Since it is an array of object and the v-model accepts only an array with value, I need to extract the id of the roles trough the computed property computedRoles.
The current roles of my user are received and assigned to userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}].
computedRoles is then equals to [1,3]
The preselection of the select is fine but I can't change anything (add or remove option from the select)
What is wrong and how to fix it?
http://jsfiddle.net/3ra1jscx/3/
<div id="app">
<template>
<el-select v-model="computedRoles" multiple placeholder="Select">
<el-option v-for="item in availableRoles" :label="item.name" :value="item.id">
</el-option>
</el-select>
</template>
</div>
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}]
}
},
computed : {
computedRoles () {
return this.userRoles.map(role => role.id)
}
}
}
I agree mostly with #wostex answer, but he doesn't give you the userRoles property back. Essentially you should swap computedRoles and userRoles. userRoles becomes a computed property and computedRoles is a data property. In my update, I changed the name of computedRoles to selectedRoles.
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
selectedRoles:[1,2]
}
},
computed : {
userRoles(){
return this.availableRoles.reduce((selected, role) => {
if (this.selectedRoles.includes(role.id))
selected.push(role);
return selected;
}, [])
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
And here is the fiddle.
Check the solution: jsfiddle
The caveat here is that computed properties are getters mainly. You can define setter for computed property, but my approach is more vue-like in my opinion.
In short, instead of v-model on computed set v-model for data property.
Full code:
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui/lib/index.js"></script>
<div id="app">
<template>
<el-select v-model="ids" multiple placeholder="Select" #change="logit()">
<el-option v-for="item in availableRoles" :label="item.name" :value="item.id">
</el-option>
</el-select>
</template>
</div>
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}],
ids: []
}
},
mounted() {
this.ids = this.userRoles.map(role => role.id);
},
methods: {
logit: function() {
console.log(this.ids);
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')

Categories

Resources