How to loop in Vue.js? - javascript

I'm trying to create a menu with vue.js, but my menu isn't showing up. Here is what I have tried:
<div id="app" class="container">
<b-menu v-for="menu in menu_items" v-bind:data="menu.menu_list" v-bind:key="menu.menu_list">
<label>{{ menu.menu_list }} </label>
<b-menu-list v-for="menu_item in menu_items.menu_list" v-bind:data="menu_item" v-bind:key="menu_item.message">
<b-menu-item > {{ menu.message }}</b-menu-item>
</b-menu-list>
</b-menu>
</div>
And here is my Vue.js code:
var App = new Vue({
el: '#app',
data: {
menu_items: [{
menu_list : 'General' [
{ message: 'First Menu' },
{ message: 'Second Menu' }
],
menu_list : 'Setting' [
{ message: 'First Setting Menu' },
{ message: 'Second Setting Menu' }
]
}]
}
})
Any solution(s)?
What i want to achieve
- General
- First Menu
- Second Menu
- Setting
- First setting Menu
- Second setting Menu

I'd suggest an alternate data structure.
menu_items: [
{
label: "General",
items: [
{
message: 'First Menu'
},
{
message: 'Second Menu'
}
]
},
{
label: "Settings",
items: [
{
message: 'First Setting Menu'
},
{
message: 'Second Setting Menu'
}
]
}
]
In the above structure, each menu is an object that has a label and a list of menu items.
Then you could build your template this way:
<b-menu v-for="menu in menu_items" v-bind:key="menu.label">
<label>{{ menu.label }}</label>
<b-menu-list v-for="item in menu.items" v-bind:key="item">
<b-menu-item> {{ item.message }}</b-menu-item>
</b-menu-list>
</b-menu>
I took out the v-bind:data properties. I'm not sure what they are for.

I'm not sure how you want to format your data, but you should probably change your data structure.
This is an example that might help you out though:
var App = new Vue({
el: '#app',
data: {
menu_items: [{
general: [
{ message: 'First Menu' },
{ message: 'Second Menu' }
],
setting: [
{ message: 'First Setting Menu' },
{ message: 'Second Setting Menu' }
]
}]
}
})
https://jsfiddle.net/5tLxdxds/

Here's my solution if you want to pass label directly from data
var App = new Vue({
el: '#app',
data: {
label1='General',
label2='Settings',
menu_items: [
{
items:[
{
message:'first menu'
},
{
message:'second menu'
}
]
label = this.label1;
},
{
items:[
{
message:'first Settings menu'
},
{
message:'second Settings menu'
}
]
label = this.label2;
},
]
}
});
Now To render it in html code :
<b-menu v-for="menu in menu_items" :key="menu.label">
<label>{{ menu.label }}</label>
<b-menu-list v-for="item in menu.items" :key="item">
<b-menu-item> {{ item.message }}</b-menu-item>
</b-menu-list>
</b-menu>
This is alternate solution if you want to pass your particular label name as data else anywhere
Hope you got perfect help!

Related

toggle tabs with vue props not working - Quasar

I have quasar tabs that are being rendered in v-for loop.
Problem is that when I provide array as prop from parent, then my tabs stop working to toggle whereas it works with local array.
<div v-for="test in tests">
<q-tabs
v-model="test.status"
align="justify"
>
<q-tab
v-for="(tab, tabIndex) in tabs"
:key="tabIndex"
:name="tab.value"
>
{{ tab.name }}
</q-tab>
</q-tabs>
</div>
<script>
export default {
props: ['tests']
data (){
return {
tabs: [
{
name: 'Required',
value: 'required'
},
{
name: 'Not Required',
value: 'not-required'
}
]
}
}
Tests Data
[
{
id: "test 1"
name: 'TEST 1'
status: 'required'
},
{
id: "test 2"
name: 'TEST 2'
status: 'not-required'
}
]
Expected result
Toggle of tabs must work when component is provided with props data to iterate.

use fetched info in an array in vue.js

I have this array:
data() {
return {
landingInfo: null,
slides: [
{
title: `this`,
},
{
title: "that",
},
{
title: "those",
},
],
};
},
Which is being displayed this way:
<div
class="slide"
v-for="(slide, index) in slides"
:key="index",
}"
>
<div>
<h1 class="text-bold">{{ slide.title }}</h1>
</div>
The problem is that I'm fetching info from and api and once I try to do:
slides: [
{
title: {{ landingInfo.data.subtitle }},
},
{
title: {{ landingInfo.data.subtitle2 }},
},
{
title: {{ landingInfo.data.subtitle3 }},
},
],
Everything explodes, I am new in vue using Nuxt.js and I cannot find any solution in how to achieve that.
Can someone show me how to include the fetched info inside the array property?
PD: I already tried using "{{thefetchedinfo}}" but it takes it literally that way and displays "{{thefetchedinfo}}"
The OP doesn't provide much info on the fetch, like when it is performed or what the returned data looks like, but the common pattern goes like this...
// <template> as in the OP, then...
data() {
return {
landingInfo: null,
slides: [], // empty before the fetch
};
},
mounted () {
fetchFromTheAPI().then(landingInfo => {
// More commonly, you'd map over the returned data to form slides,
// or, trying to match the OP...
this.slides = [
{ title: landingInfo.data.subtitle },
{ title: landingInfo.data.subtitle2 }, // ... and so on
]
});
},

Using vuetify.js to create a table and sub table -- not sure where to start

So we have a system of tasks and replies, and I need to present this in a web application. Our dev team uses vuetify.js, but I haven't found any examples in our current repo if what I'm trying to do.
I basically need to build a table with the Task details like subject, date, assigned to, etc, then below each Task row show all the replies which will have a different set of headers. I guess from a SQL standpoint it'd be the replies grouped by the parent task. The closest thing I found was Grouped Rows, but this seemed to group by just a single field. I need two distinct headers between the main table and sub tables which I haven't found any examples of.
An example I guess would be this:
ID Subject Assigned To Date Status
123 Need to do something John B 2020-02-01 Active
Mike R User request was submitted 2020-02-01
John B Called User 2020-02-01
Mary Q User called back with details 2020-02-02
John B Waiting on pc support to fix 2020-02-03
223 Need to do something else Jason Q 2020-02-04 Closed
Tom E User Email - Password Reset 2020-02-04
Jason Q Called user and reset password 2020-02-04
Admittedly I'm new to Javascript and using vue or vuetify.js, but if I can find an example of this that'll be enough to get me running.
Thanks for the advise on this project.
You could do something along these lines, using Expandable rows and scoped slots:
Vue.config.productionTip = false;
Vue.component('my-component', {
template: '#my-component',
data() {
return {
headers: [
{ text: 'ID', value: 'id' },
{ text: 'Subject', value: 'subject' },
{ text: 'Assigned To', value: 'assignedTo' },
{ text: 'Date', value: 'date' },
{ text: 'Status', value: 'status' }
],
replyHeaders: [
{ text: 'Title', value: 'title' },
{ text: 'Date', value: 'date' }
],
tasks: [
{
id : 123,
subject: 'Need to do something',
assignedTo: 'John B',
date: '2020-02-01',
status: 'Active',
replies: [
{ id: 1, title: 'User request was submitted', date: '2020-02-01'},
{ id: 2, title: 'Called User', date: '2020-02-01'},
{ id: 3, title: 'User called back with details', date: '2020-02-02'},
{ id: 4, title: 'Waiting on pc support to fix', date: '2020-02-03'}
]
},
{
id : 223,
subject: 'Need to do something else',
assignedTo: 'Jason Q',
date: '2020-02-04',
status: 'Closed',
replies: [
{ id: 5, title: 'User Email - Password Reset', date: '2020-02-04'},
{ id: 6, title: 'Called user and reset password', date: '2020-02-04'}
]
}
],
};
}
});
var vm = new Vue({
el: '#app',
vuetify: new Vuetify()
});
.sub-table.theme--light.v-data-table { background: transparent; }
.sub-table .v-data-table-header { display: none; }
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet"> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script><style>.as-console-wrapper{display: none!important}</style>
<div id="app">
<v-app>
<my-component></my-component>
</v-app>
</div>
<template id="my-component">
<v-data-table
:headers="headers"
:items="tasks"
item-key="id"
class="elevation-1"
show-expand
>
<template v-slot:expanded-item="{ headers, item }">
<td :colspan="headers.length">
<v-data-table
class="sub-table"
:headers="replyHeaders"
:items="item.replies"
item-key="id"
class="elevation-0"
hide-default-footer
></v-data-table>
</td>
</template>
</v-data-table>
</template>

Use a template in vue component passed as a prop

I'm a total newbie, so please bear with me if I'm still grasping with the coding fundamentals.
I want to use a template that is defined in the prop. The template is inside the DOM. The reason I want to do it this way is that I want to reuse the component logic (specifically the pagination), but may want to change how the way the template displays the data in different pages. So I wanted to seaparate the template from the script file.
This is the HTML File:
<div id="store-list">
<paginated-list :list-data="stores" use-template="#displayList"></paginated-list>
</div>
<script type="text/template" id="display-list">
<div>
<div v-for="p in paginatedData">
{{p.BusinessName}}
</div>
</div>
</script>
This is the .js file:
Vue.component('paginated-list', {
data() {
return {
pageNumber: 0
}
},
props: {
listData: {
type: Array,
required: true
},
useTemplate: {
type: String,
required: false
},
size: {
type: Number,
required: false,
default: 10
}
},
computed: {
pageCount() {
let l = this.listData.length,
s = this.size;
return Math.floor(l / s);
},
paginatedData() {
const start = this.pageNumber * this.size,
end = start + this.size;
return this.listData
.slice(start, end);
}
},
//template: document.querySelector('#display-list').innerHTML // this works
template: document.querySelector(useTemplate).innerHTML // this does not
});
var sl = new Vue({
el: '#store-list',
data: {
stores: [{
"BusinessName": "Shop Number 1"
}, {
"BusinessName": "Shop Number 2"
}, {
"BusinessName": "Shop Number 3"
}]
}
});
var shoppingList = new Vue({
el: '#shopping-list',
data: {
header: 'shopping list app',
newItem: '',
items: [
'1',
'2',
'3',
]
}
})
Any help is greatly appreciated. Thank you.
You can use the inline-template attribute to override the component's template at render time. For example
<paginated-list :list-data="stores" inline-template>
<div>
<div v-for="p in paginatedData">
{{p.BusinessName}}
</div>
</div>
</paginated-list>
See https://v2.vuejs.org/v2/guide/components-edge-cases.html#Inline-Templates
Your component can still have a default template but this will override it if set.

bootstrap-vue - table won't get updated after AJAX request (vue2.js)

I'm pretty new with vue.js and I saw this great library that doing exactly what I need for my project: Boostrap-Vue
example source code
I followed the basic instructions and I've added an small change, ajax call for dynamic content:
<layout :docs="docs">
<template slot="demo">
<b-table
stripped
hover
:items="items"
:fields="fields"
:current-page="currentPage"
:per-page="perPage"
:filter="filter"
>
<template slot="name" scope="item">
{{item.value.first}} {{item.value.last}}
</template>
</b-table>
</template>
</layout>
export default {
mounted () {
this.get_data();
},
data() {
return {
docs: {
component: 'bTable'
},
items: [],
fields: {
name: {label: 'Person Full name', sortable: true},
},
currentPage: 1,
perPage: 5,
filter: null
};
},
methods: {
get_data () {
this.$http.get("myapp/users").then(res => {
if (res.body) {
this.items = res.body;
} else {
this.error = true;
}
});
}
}
};
So the problem is - after I'm getting the Ajax response and the "items" variable initialized with the data but the table still won't get update.
The strangest part is that with static data its works fine (as shown in the example source code, without AJAX).
Any idea why?
Thanks!!!
I found the problem, it seems that it necessary to define the following fields according to the value I received in the response:
fields: {
name: {label: 'Person Full name', sortable: true},
}
so if my json looks like this:
{user_name: "user"}
it should look like this:
fields: {
user_name: {label: 'Person Full name', sortable: true},
}
Anyway, Yoram de Langen Thanks for the help!
Did you try to debug the res.body and what it contains? What is the structure your myapp/users returns? Do you return the structure directly like so:
[
{ "name": "item 1"},
{ "name": "item 1"},
]
or does it look like this:
{
"result": [
{ "name": "item 1"},
{ "name": "item 1"},
]
}
In case of the latest one your this.items = res.body should be: this.items = res.body.result

Categories