Reputation: 624
I want to create a webpage containing several button groups. The existing code is
$(document).ready(function() {
$(".nav-link").click(function() {
console.log(this);
});
});
Vue.component('nav-bar', {
props: ['navs'],
template: `<ul class="nav">
<li v-for="nav in [{id: 0, text: 'Vege'}, {id:1, text: 'Ch'}]"
v-bind:item="nav"
v-bind:key="nav.id">
<a class="nav-link" v-on:click="setactive($event)">{{ nav.text }}</a></li>
</ul>`,
methods: {
setactive: function(event) {
$(event.target).closest('ul').find('a.active').removeClass('active');
$(event.target).addClass('active');
},
created: function() {
$(this).find('a').first().addClass('active');
}
}
});
var app = new Vue({
el: '#app',
data: {
navs: [
{ id: 0, text: 'Vegetables' },
{ id: 1, text: 'Cheese' },
{ id: 2, text: 'Milk' }
]
}
});
.nav {
display: flex;
flex-wrap: wrap;
list-style: none;
}
.nav-link.active {
color: #fff;
background-color: #007bff;
}
.nav-link {
color: #4183c4;
text-decoration: none;
background-color: transparent;
border-radius: .25rem;
padding: .5rem 1rem;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="app">
<nav-bar></nav-bar>
</div>
My problems are:
<li v-for="nav in [{id: 0, text: 'Vege'}, {id:1, text: 'Ch'}]"
to <li v-for="nav in navs"
, nothing is displayed at all. Whats wrong with that?active
upon creation?<nav-bar>
?I do not want to use bootstrap
button-groups.
Upvotes: 2
Views: 2501
Reputation: 138286
if changing
<li v-for="nav in [{id: 0, text: 'Vege'}, {id:1, text: 'Ch'}]"
to<li v-for="nav in navs"
, nothing is displayed at all. Whats wrong with that?
That depends on the value of navs
. We'd need to see the exact code to troubleshoot.
how can the nav items be given directly to
<nav-bar>
?
To pass the value of navs
from App
to <nav-bar>
, use v-bind
:
<div id="app">
<nav-bar v-bind:navs="navs" />
<!-- OR shorthand for v-bind -->
<nav-bar :navs="navs" />
</div>
why isn't the first item's class set to
active
upon creation?
The DOM hasn't yet been stamped in the created
lifecycle hook, so jQuery isn't able to find the element to set active. Since the elements you're querying are dynamically added (via the navs
prop), you'd have to:
Wait until the navs
prop changes (instead of using a lifecycle hook). Use a watcher for this:
Vue.component('nav-bar', {
watch: {
navs: {
handler() { /* SEE NEXT STEP */ },
immediate: true, // call handler immediately in case `navs` data is already available
}
}
})
Wait until the elements are added to the DOM in $nextTick
.
// in watch:
handler() {
this.$nextTick(() => {
$(this).find('a').first().addClass('active');
});
},
Vue.component('nav-bar', {
props: ['navs'],
template: `<ul class="nav" ref="list">
<li v-for="nav in navs"
v-bind:item="nav"
v-bind:key="nav.id">
<a class="nav-link" v-on:click="setactive($event)">{{ nav.text }}</a>
</li>
</ul>`,
methods: {
setactive: function(event) {
$(event.target).closest('ul').find('a.active').removeClass('active');
$(event.target).addClass('active');
},
},
watch: {
navs: {
immediate: true,
handler() {
this.$nextTick(() => {
$(this.$refs.list).find('a').first().addClass('active');
});
}
}
}
});
var app = new Vue({
el: '#app',
data: {
navs: [{
id: 0,
text: 'Vegetables'
},
{
id: 1,
text: 'Cheese'
},
{
id: 2,
text: 'Milk'
}
]
}
});
.nav {
display: flex;
flex-wrap: wrap;
list-style: none;
}
.nav-link.active {
color: #fff;
background-color: #007bff;
}
.nav-link {
color: #4183c4;
text-decoration: none;
background-color: transparent;
border-radius: .25rem;
padding: .5rem 1rem;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="app">
<nav-bar :navs="navs"></nav-bar>
</div>
Upvotes: 1