VueJS Primevue TreeSelect - vuejs3

I put a component from PrimeVue: TreeSelect in my VueJS code
It works fine, but now how to know which box is selected?
< TreeSelect v-model="selectedNode" :options="options" selectionMode="checkbox" :metaKeySelection="false" placeholder="Select Items"> < /TreeSelect>
I succeed to print that:
{{selectedNode}}
<ul>
<li v-for="check in selectedNode">
{{check}}
</li>
</ul>
The result:
{ "0": { "checked": false, "partialChecked": true }, "0-0": { "checked": true, "partialChecked": false } }
{ "checked": false, "partialChecked": true }
{ "checked": true, "partialChecked": false }
My problem is that I don't know how to just have the keys (0, 0-0...)

The response uses object keys, so you can just use those with Object.keys
If you're doing it in the template, just watch out for the value being null.
<ul>
<li v-for="check in Object.keys(selectedNode || {})">
{{ check }}
</li>
</ul>

Related

Vue3 Dropdown Click ul show

I want to do something like this in my project below, but every time I click it, it seems as if each element is selected.
What I want to do is simply,
When handleShow(depth) is clicked;
I want to print the clicked depth value in selected and show its ul, but it does not satisfy the condition I wrote.
v-show="selected === depth"
<template>
<li v-if="items.children" class="item dropdown">
<router-link
:link="items"
:key="depth"
#click.stop="handleShow(depth)"
/>
<ul class="dropdown-menu" v-show="selected === depth">
<MenuItems
v-for="(child, childIndex) in items.children"
:key="childIndex"
:items="child"
/>
</ul>
</li>
<li v-else class="item">
<router-link
:link="items"
:key="depth"
/>
</li>
</template>
<script>
import {ref, defineComponent} from "vue"
export default defineComponent({
name: 'MenuItems',
components: {MenuLink},
props: {
items: {type: Object, required: true},
depth: Number,
},
setup() {
let selected = ref(null);
const handleShow = (depth) => {
selected.value = depth;
}
return {
handleShow,
selected
}
},
})
</script>

How to remove active class of previously selected list item on selecting new one in angular

I want to remove the active class of list item which I had set intentionally active so when the page load I want this list item to remain active using routerLinkActive="active". I want to disable this active class when I select the other items of list in angular
I tried using ngClass but didn't worked as expected. How can this be done without using jquery?
<ul class="nav">
<li routerLinkActive="active" *ngFor="let menuItem of menuItems" [ngClass]="{'active': selectedItem == menuItem}" (click)="listClick($event, menuItem)">
<a class="nav-link" [routerLink]="[menuItem.path]">
<p>{{ menuItem.title }}</p>
</a>
</li>
</ul>
declare interface RouteInfo {
path: String,
title: String,
class: String
}
export const ROUTES: RouteInfo[] = [
{ path: '', title: 'Dashboard', class: '' },
{ path: '/vessel', title: 'Vessel Details', class: '' },
{ path: '/arrival', title: 'Arrival Details', class: ''},
{ path: '/stock', title: 'StockYard', class: ''},
{ path: '/cargo', title: 'Cargo Details', class: '' },
{ path: '/other', title: 'Others', class: ''}
];
menuItems: any[];
selectedItem= false;
listClick(event, newValue) {
console.log(newValue);
this.selectedItem = !this.selectedItem;
}
The intentionally setted active class should be disabled when other list items are clicked.
I see what your trying to do now. You shouldn't need to use ngClass or the click event. Angular will check to see if the active route matches the routerLink path. If it does, the class specified in ActiveRouterLink is added.
It's hard to solve your issue without knowing what you are seeing but try adding [routerLinkActiveOptions]="{exact: true} to the li element.

Pass data to afterClose

I am using FancyBox 3 , i need to pass data to the afterClose and trigger this data after closing the Iframe .
<a data-fancybox data-type="iframe"
data-src="{{route('tbl_properties.getApartmentsForLegal3',[$property->id,$group_id])}}"
href="javascript:;" type="button" class="btn btn-info " title="Show Apartments" data-reference="{{$property->property_reference}}">
<i class="nav-icon i-Home-Window fa-4x "></i>
</a>
jquery :
$('[data-fancybox]').fancybox({
property_reference :$(this).data('reference'),
iframe: {
preload: false
},
fullScreen: {
autoStart: true
},
afterClose: function(instance, slide ,property_reference) {
alert(property_reference);
window.location.reload();
}
});
the data is the property_reference.
thanks
current.opts.$orig will be reference to current trigger element (e.g., your link), and you can use that to retrieve custom data, example:
$('[data-fancybox]').fancybox({
iframe: {
preload: false
},
fullScreen: {
autoStart: true
},
afterClose: function(instance, current) {
alert(current.opts.$orig.data('reference'));
}
});
Demo - https://codepen.io/anon/pen/bPKVpB?editors=1010

Vue v-if not reading variable

I am using Vue 2 on Laravel 5.3 (using bxslider for carousel)
The following code gives me a single image (img1) slider.
If I remove v-ifs it does give me 3 image (with img1 img2 img3 in the slider).
Does productChoiceSelected.img2 returns true if it is not null from the database?
EDIT (added full code of the component)
<div class="col-md-4">
<ul class="bxslider">
<li>
<img :src="productChoiceSelected.img1">
</li>
<li v-if="productChoiceSelected.img2">
<img :src="productChoiceSelected.img2">
</li>
<li v-if="productChoiceSelected.img3">
<img :src="productChoiceSelected.img3">
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data(){
return{
product:[],
productChoiceSelected:[],
productChoices:[]
}
},
props:[
'productId'
],
mounted(){
this.getProduct()
this.getAllProductChoices()
},
methods:{
getProduct(){
var vm = this;
vm.$http.get('/getProduct/'+vm.productId).then((response)=>{
vm.product = response.data.data.product;
vm.productChoiceSelected = response.data.data.productChoiceDefault;
});
},
getAllProductChoices(){
var vm = this;
vm.$http.get('/getAllProductChoices/'+vm.productId).then((response)=>{
vm.productChoices = response.data.data.productChoices;
});
}
}
}
</script>
EDIT #2
I guess it is because productChoiceSelected.img2 is a url directory? it is http://localhost:8000/img/products/1-2.bmp
I can figure out few issues in your code:
You need to have img1 and these variables defined as these are to be set reactively to be used in vue templated.
You need to move $('.bxslider').bxSlider({}) code in the updated section as this needs to be executed once you get the data updated from backend.
Following are code changes:
var demo = new Vue({
el: '#demo',
data: function(){
return {
productChoiceSelected: {
img1:'',
img2:'',
img3:''
}
};
},
mounted(){
this.getProduct()
},
updated(){
$('.bxslider').bxSlider({});
},
methods:{
getProduct(){
var vm = this;
setTimeout(function () {
vm.productChoiceSelected.img1 = 'http://bxslider.com/images/730_200/hill_trees.jpg'
// vm.productChoiceSelected.img2 = 'http://bxslider.com/images/730_200/houses.jpg'
vm.productChoiceSelected.img3 = 'http://bxslider.com/images/730_200/hill_fence.jpg'
}, 300)
}
}
})
see updated fiddle.
Thanks for saurabh contribution above, as I am still unsure where the problem is, here is how I solve the problem by myself for you guys' reference.
Change in code:
<template>
<div class="col-md-5">
<div class="col-md-12">
<ul class="bxslider">
<li>
<img :src="productChoiceSelected.img1">
</li>
<li v-if="img2">
<img :src="productChoiceSelected.img2">
</li>
<li v-if="img3">
<img :src="productChoiceSelected.img3">
</li>
</ul>
</div>
</div>
.....
.....
.....
methods:{
getProduct(){
var vm = this;
vm.$http.get('/getProduct/'+vm.productId).then((response)=>{
vm.product = response.data.data.product;
vm.productChoiceSelected = response.data.data.productChoiceDefault;
if(vm.productChoiceSelected.img1){
vm.img1 = true
}
if(vm.productChoiceSelected.img2 != null){
vm.img2 = true
}
if(vm.productChoiceSelected.img3 != null){
vm.img3 = true
}
});
},
......
......
......

Vue JS - Rendering Multidemensional Obj

I'm new to VUE, and having a hard time figuring out how to render an Object where i don't know how many levels deep it will go.
i get this object returned from a web-api
var result = {
"1":{
"id":"1",
"parent_id":"-1",
"name":"Master",
"level":1,
"children":{
"2":{
"id":"2",
"parent_id":"1",
"name":"Category A",
"level":2,
"children":{
"5":{
"id":"5",
"parent_id":"2",
"name":"Category D",
"level":3
},
"6":{
"id":"6",
"parent_id":"2",
"name":"Category E",
"level":3,
"children":{
"10":{
"id":"10",
"parent_id":"6",
"name":"Category F",
"level":4
}
}
}
}
},
"3":{
"id":"3",
"parent_id":"1",
"name":"Category B",
"level":2,
"children":{
"4":{
"id":"4",
"parent_id":"3",
"name":"Category C",
"level":3
}
}
}
}
}
};
I ignore the first level and push it in my store. Now i'm looking for a recursive way to go over all the parent's and theire children.
(this would be an example of the desired output)
<ul>
<li>Master</li>
<ul>
<li>Category A</li>
<ul>
<li>Category D</li>
<li>Category E</li>
<ul>
<li>Category F</li>
</ul>
</ul>
<li>Category B</li>
<ul>
<li>Category C</li>
</ul>
</ul>
</ul>
However i do not get further then:
<ul>
<li>Master</li>
<ul>
<li>Category A</li>
<li>Category B</li>
</ul>
</ul>
And offcourse i could go on like this and then i'll reach the end of my obj. but in real situation i don't know how deep it will go, that's why i want a solution that doesn't care about that and continiu's till there are no more children.
I saw a little something in the doc's but that code is so different from mine that i cant really understand how to apply ( https://v2.vuejs.org/v2/guide/components.html#Circular-References-Between-Components )
My init code is basically this is everything (simplified) together :
store = function() {
var self = this;
self.hierarchies = [];
self.subView = 'hierarchies';
self.tree = [];
};
Vue.component('hierarchies', {
template: '#hierarchies',
props: ['store']
});
Vue.component('products', {
template: '#products',
props: ['store']
});
Vue.component('treeview', {
template: '#treeview',
props: ['store']
});
app = new Vue({
el: '#content',
data: function () {
return {
store: {},
tree: {}
}
},
created: function () {
this.store = new store();
}
});
// DO AXJAX REQUEST GET HIERARCHY'S
var response = // AJAX {};
app.store.tree.push(response[1]);
<template id="treeview">
<div>
<ul v-if="store.tree.length">
<li v-for="m in store.tree">
{{ m.name }}
<ul v-if="m.children">
<li v-for="c in m.children">
{{ c.name }}
</li>
</ul>
<data :tree="m"></data>
</li>
</ul>
</div>
</template>
All idea's suggestions are welcome :)
Best,
Bastian
Your data is in a pretty unpractical format since you cannot loop over object keys using the v-for directive. So in order to consume that format, you have to transform it into an array first. I’m using a computed property for that, but a better solution for the long run might be to transform the data once in the beginning or even changing the result format of your web service (if you can).
var result = {"1":{"id":"1","parent_id":"-1","name":"Master","level":1,"children":{"2":{"id":"2","parent_id":"1","name":"Category A","level":2,"children":{"5":{"id":"5","parent_id":"2","name":"Category D","level":3},"6":{"id":"6","parent_id":"2","name":"Category E","level":3,"children":{"10":{"id":"10","parent_id":"6","name":"Category F","level":4}}}}},"3":{"id":"3","parent_id":"1","name":"Category B","level":2,"children":{"4":{"id":"4","parent_id":"3","name":"Category C","level":3}}}}}};
Vue.component('tree-root', {
props: ['items'],
template: `
<ul>
<tree-item v-for="item in items" v-bind:item="item"></tree-item>
</ul>
`
});
Vue.component('tree-item', {
props: ['item'],
computed: {
children: function () {
return Object.keys(this.item.children).map(k => this.item.children[k]);
}
},
template: `
<li>
{{item.name}}
<tree-root v-if="item.children" v-bind:items="children"></tree-root>
</li>
`
});
var app = new Vue({
el: '#app',
data: {
rootItem: result['1']
}
});
<ul id="app">
<tree-item v-bind:item="rootItem"></tree-item>
</ul>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
What I’m doing here is use two components: tree-root which is responsible for rendering a list of items, and tree-item which is responsible for rendering a single item, eventually recursively rendering another tree-root for the children of each item.
The computed children property is used to transform the children object into a list of children.
Finally, in order to render the root component, we just render the result['1'] which is the root element as a tree-item. We could also render a tree-root instead with the whole result but then we would have to convert it first into an array (just like in the computed property), so I just opted with the simpler solution here.

Resources