Vue not passing data in component - javascript

I am not sure why the data is undefined despite passing the right property from the component.
This is my vue component
Vue.component('store-squaretile-component',{
template: '#store-squaretile-component',
props: [
'storeName'
],
data: function () {
return {}
},
});
This is its template
<script type='text/x-template' id='store-squaretile-component'>
<div class="stores-squaretile__container">
<div class="stores-squaretile__btn stores-squaretile__btn--shadow" >
<!-- background of store-squaretile to be set to img -->
<div class="dropdown">
<div class="stores-squaretile__threedots" data-bs-toggle="dropdown" >
<i class="fas fa-ellipsis-v"></i>
</div>
<ul id="dropdown-menu-store" class="dropdown-menu" >
<div class="'dropdown-item dropdown-title">Quick Actions</div>
<div class="dropdown-line"></div>
<a class="dropdown-item" href="#">Edit Store</a>
<a class="dropdown-item" href="#">Delete Store</a>
</ul>
</div>
</div>
<div class="stores-squaretile__title">{{storeName}}</div>
</div>
</script>
When i pass the component this array:
stores: [
{name: "harry's",},
{name: "Carl's junior",},
{name: "Mcdonald's",}
]
into this component
<store-squaretile-component
v-for="store in stores"
:storeName="store.name"
></store-squaretile-component>
it is suppose to suppose to replace the storeName with the name in the array but instead I get a NaN or the title disappears entirely.
I received an undefined value. Is there a reason for this?

It's working fine, just replaced storeName with storename and added :key to v-for loop:
Vue.component('store-squaretile-component', {
template: '#store-squaretile-component',
props: ['storename'],
})
new Vue({
el: '#demo',
data() {
return {
stores: [
{name: "harry's", },
{name: "Carl's junior",},
{name: "Mcdonald's",}
]
}
}
})
Vue.config.productionTip = false
Vue.config.devtools = false
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<store-squaretile-component
v-for="(store, idx) in stores"
:storename="store.name"
:key="idx"
></store-squaretile-component>
</div>
<script type='text/x-template' id='store-squaretile-component'>
<div class="stores-squaretile__container">
<div class="stores-squaretile__btn stores-squaretile__btn--shadow" >
<div class="dropdown">
<div class="stores-squaretile__threedots" data-bs-toggle="dropdown" >
<i class="fas fa-ellipsis-v"></i>
</div>
<ul id="dropdown-menu-store" class="dropdown-menu" >
<div class="'dropdown-item dropdown-title">Quick Actions</div>
<div class="dropdown-line"></div>
<a class="dropdown-item" href="#">Edit Store</a>
<a class="dropdown-item" href="#">Delete Store</a>
</ul>
</div>
</div>
<div class="stores-squaretile__title">{{storename}}</div>
</div>
</script>

Related

Vue/Nuxt app is rendering content (not components, just content) twice on every page

I am very new to Vue/Nuxt programming and followed a "add a blog" tutorial which I then modified for my site. It all works perfectly except the actual it is rendering content twice. It renders
NavPage (component) > content > FooterDiv(component) then content again. See image:
Image of the page showing duplicated content
This happens on every page.
I am including my blogpage code ecasue in testing it seems to be where the problem lives :
<template>
<div>
<div class="home-page">
<h2>Latest Posts</h2>
<div class="articles">
<div class="article" v-for="article of articles" :key="article.slug">
<nuxt-link :to="{ name: 'slug', params: { slug: article.slug } }">
<div class="article-inner">
<img :src="require(`~/assets/resources/${article.img}`)" alt="" />
<div class="detail">
<h3>{{ article.title }}</h3>
<p>{{ article.description }}</p>
</div>
</div>
</nuxt-link>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "BlogPage",
data() {
return {
name: ''
}
},
mounted() {
let user = localStorage.getItem('user-info');
if (!user) {
this.$router.push({ name: "BlogPage" })
}
},
async asyncData({ $content, params }) {
const articles = await $content('articles', params.slug)
.only(['title', 'description', 'img', 'slug'])
.sortBy('createdAt', 'asc')
.fetch()
return {
articles
}
}
}
I have also included the structure being rendered by Vue per the Vue Dev Tools
This image is what I see in the dev tools when the page is rendered
I have spent hours troubleshooting this and can find no other info on the issue.
Thank you for any help, and your patience with a newbie. Let me know if you need to see any other code.
As requested here is my NavPage component code:
<template>
<!-- Navigation-->
<nav class="navbar navbar-expand-lg bg-secondary text-uppercase fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand" href="#page-top">Denise Pedro</a>
<button class="navbar-toggler text-uppercase font-weight-bold bg-primary text-white rounded" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
Menu
<i class="fas fa-bars"></i>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ms-auto">
<li class="navbar-brand"> <NuxtLink to="/">Home</NuxtLink></li>
<li class="navbar-brand"> <NuxtLink to="/PortfolioPage">Portfolio</NuxtLink></li>
<li class="navbar-brand"> <NuxtLink to="/ResumePage">Resume</NuxtLink></li>
<li class="navbar-brand"> <NuxtLink to="/ContactPage">Contact</NuxtLink></li>
<li class="navbar-brand"> <NuxtLink to="/BlogPage">Blog</NuxtLink></li>
</ul>
</div>
</div>
</nav>
</template>
and my FooterDiv component
<template>
<!-- Footer-->
<footer class="footer text-center">
<div class="container">
<div class="row">
<!-- Footer Location-->
<div class="col-lg-4 mb-5 mb-lg-0">
<h4 class="text-uppercase mb-4">Location</h4>
<p class="lead mb-0">
Seattle through Olympia, WA
<br />
</p>
</div>
<!-- Footer Social Icons-->
<div class="col-lg-4 mb-5 mb-lg-0">
<h4 class="text-uppercase mb-4">Around the Web</h4>
<!-- <a class="btn btn-outline-light btn-social mx-1" href="#!"><font-awesome-icon icon="fa-brands fa-facebook" /></a> -->
<a class="btn btn-outline-light btn-social mx-1" href="#!"><img src="../assets/img/facebook-brands.svg" alt="facebook icon" /></a>
<a class="btn btn-outline-light btn-social mx-1" href="#!"><img src="../assets/img/twitter-brands.svg" alt="twitter icon"/></a>
<a class="btn btn-outline-light btn-social mx-1" href="#!"><img src="../assets/img/linkedin-in-brands.svg" alt="linkedin icon"/></a>
</div>
<!-- Footer About Text-->
<div class="col-lg-4">
<h4 class="text-uppercase mb-4">Denise Pedro</h4>
<p class="lead mb-0">
desiraes#gmail.com
<!-- Start Bootstrap -->
</p>
</div>
</div>
</div>
</footer>
</template>
and lastly, my layout code
<template>
<div>
<NavPage />
<Nuxt />
<FooterDiv />
<Nuxt />
</div>
</template>
<script>
import NavPage from '../src/components/NavPage.vue';
import FooterDiv from '../src/components/FooterDiv.vue'
export default {
components: {
NavPage,
FooterDiv
},
}
</script>
Thank you
In your layout, you've put </Nuxt> twice, that's why the page content is duplicated, you should remove it.
your layout.vue should look like that:
<template>
<div>
<NavPage />
<Nuxt />
<FooterDiv />
</div>
</template>
<script>
import NavPage from '../src/components/NavPage.vue';
import FooterDiv from '../src/components/FooterDiv.vue'
export default {
components: {
NavPage,
FooterDiv
},
}
</script>

How to change <select> value on Vuejs3?

I wanted to change <select> value getting ul > li value and use this value id on <select> v-model.
<div>
<select id="selected" #click="show-modal" v-model="subcategory_id">
<option></option>
</select>
</div>
<div class="modal">
<header class="modal-card-head">
<p class="modal-card-title">Choose category</p>
<button #click.prevent="close-modal" class="delete" aria-label="close"></button>
</header>
<section class="modal-card-body">
<div class="card ">
<ul class="cl-menu">
<li v-for="category in categories" :key="category.id" >
<a href="#">{{category.name}}
<ul>
<li #click="getLi(sub)" v-for="sub in category.subcategory" :key="sub.id">
<a class="px-2" href="#">{{sub.name}}</a>
</li>
</ul>
</li>
</ul>
</div>
</section>
</div>
Vuejs
getLi: function(e) {
const m = document.querySelector('.modal');
document.getElementById("selected").options[0].value = e.name;
m.classList.toggle('is-active')
console.log(e.name)
}
I am able to get value from list but cannot pass it to select value and value`s id to v-model.
Thanks in advance
Instead of manipulating the DOM as #Thomas said, you should make use of Vue's data binding:
new Vue({
el: '#app',
template: `<div><div>
<select id="selected" #click="show-modal" v-model="subcategory_id" disabled>
<optgroup v-for="category in categories" :key="category.id" :label="category.name">
<option v-for="sub in category.subcategory" :key="sub.id" :value="sub.id">
{{sub.name}}
</option>
</optgroup>
</select>
<button #click="openModal">Choose</button>
</div>
<div class="modal" v-if="showModal">
<header class="modal-card-head">
<p class="modal-card-title">Choose category</p>
<button #click.prevent="closeModal" class="delete" aria-label="close">×</button>
</header>
<section class="modal-card-body">
<div class="card ">
<ul class="cl-menu">
<li v-for="category in categories" :key="category.id" >
{{category.name}}
<ul>
<li #click="getLi(sub)" v-for="sub in category.subcategory" :key="sub.id">
<a class="px-2" href="#">{{sub.name}}</a>
</li>
</ul>
</li>
</ul>
</div>
</section>
</div></div>`,
data() {
return {
showModal: true,
subcategory_id: null,
categories: [{
name: 'A',
id: 1,
subcategory: [{
name: 'A.1',
id: 2
}]
}, {
name: 'B',
id: 3,
subcategory: [{
name: 'B.1',
id: 4
}]
}]
}
},
methods: {
getLi: function(subId) {
this.subcategory_id = subId.id
this.closeModal()
},
closeModal() {
this.showModal = false
},
openModal() {
this.showModal = true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

How can I create dynamic menu with submenu in vue 2?

I have a problem and if you can help me I would be grateful, because I am working with vue for 3 weeks.
I try to create a menu with submenu in vue 2 by two weeks and I can't succeed. the menu is created , but when I go to submenu is won't create it. the code is next:
<script>
import image from "./assets/img/logo-just-escape.png"
import axios from "axios"
export default {
data(){
const lang = localStorage.getItem('lang')
return {
imagel: image,
lang: lang,
languages:null,
menu:null,
submenu:null
}
},
async created(){
try {
var res =await axios.get(`lng`);
this.languages=res.data;
const valmenu="titles/value?language="+this.lang;
res=await axios.get(valmenu);
this.menu=res.data;
this.submenu=this.getSubMnu(this.menu);
console.log(this.submenu)
}catch(e){
console.error(e);
}
},
methods: {
handleChange(event){
localStorage.setItem('lang',event.target.value);
window.location.reload();
},
getSubMnu(value){
let temp='';
let sbmenu=[];
let variable=null;
for(temp in value){
if('2'==value[temp].subtitle){
variable=value[temp];
let temp1=value[temp].link+"\/"+this.menu[temp].id;
variable.link=temp1;
sbmenu.push(variable);
}
}
return sbmenu;
}
}
}
</script>
<template>
<div id="app" class="bg-dark">
<div>
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="/">
<img width="100" height="50" :src="imagel"/>
</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<div v-for="menuButton in this.menu" :value="menuButton.title" :key="menuButton.id">
<li class="nav-item" v-if="menuButton.subtitle ===0">
<router-link :to="menuButton.link" ><span class="nav-link">{{menuButton.title}}</span></router-link>
</li>
<li class="nav-item dropdown" v-if="menuButton.subtitle ===1" style="color: white;">
<span class="nav-link dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{menuButton.title}}</span>
<div v-for="tempor in this.submenu" class="dropdown-menu dropdown-menu-right bg-dark" :value="tempor.title" :key="tempor.id">
<span class="nav-link">{{tempor.title}}</span>
<router-link :to="tempor.link" #click.name><span class="nav-link">{{tempor.title}}</span></router-link>
</div>
</li>
</div>
<li class="nav-item">
<select class="selectpicker form-control" v-model="lang" data-width="fit" #change="handleChange($event)">
<option v-for="langu in languages" :value="langu.language_short" :key="langu.id">
{{langu.language}}
</option>
</select>
</li>
</ul>
</div>
</nav>
<div class="divmargin" >
<router-view/>
</div>
</div>
</div>
</template>
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: "TypeError: Cannot read property 'submenu' of undefined"
found in
---> at src/App.vue
If someone can give me some answer to this I will be very grateful.
Thank you,
Vlad.

How to change template with vue.js?

I am a beginner of vue.js, now I try to set up a website with dynamic tab.
I have some problem when changing different tab with different template.
But I face a problem, when I click the ul element in my website to change another template, it shows error as following:
It seems like template included error.
<template id="switchhover">
<div>
<div class="menu">
<div class="title">
<img src="../assets/title.jpg" class="min_picture">
<span>Hello</span>
</div>
<ul>
<li #click="changeView('Home')" class="liststyle">Home(首頁)</li>
<li #click="changeView('WorkExperience')" class="liststyle">Work Experience(工作經歷)</li>
<li class="liststyle">Project Experience(專案經歷)</li>
<li class="liststyle">Portfolio(作品集)</li>
<li class="liststyle">Photo(相片)</li>
<li class="liststyle">
<router-link :to="{path: '/'}">Back to Navigation Page<br>(回導覽頁)
</router-link>
</li>
</ul>
<div class="link">
<a href="https://www.facebook.com/profile.php?id=100001824960776">
<div class="fb"></div>
</a>
<a href="https://github.com/PefyLi">
<div class="github"></div>
</a>
<a href="https://www.linkedin.com/in/grant-li-3a6680150/">
<div class="linkedin"></div>
</a>
</div>
</div>
<div class="content">
<div class="banner">
<div>
<div class="picture">
<img src="../assets/title.jpg" class="bar_picture">
</div>
<div>
<span style="font-size:35px;margin-right:29px">Hello</span>
<span>Hello</span><br><br><br><br>
</div>
</div>
</div>
<component :is="currentTab" keep-alive></component>
</div>
</div>
</template>
<script>
import Home from './Home';
import WorkExperience from './WorkExperience';
export default {
data(){
return{
currentTab:Home
}
},
methods:{
changeView: function(viewName) {
this.currentTab = viewName
}
},
components: {
Home:{ template: Home},
WorkExperience:{ template: WorkExperience}
},
};
</script>

How to hide panel and navbar in login page framework7

I'd like to hide correctly the panel and the navbar only in the login page. After login I'd like to show them. I achieve this task partially, because my code has a bad side effect. When I open the app I saw my login page but for few second the navbar appears and then disappears. I'd like to access on login page without this effect. I'd like to see immediatly the login page without them.
How can I solve it?
I declared them in my index.html
<div id="app">
<div class="panel panel-left panel-cover">
<div class="navbar color-theme-green ">
<div class="navbar-inner sliding">
<div class="title">Menu</div>
</div>
</div>
<div class="block">
<div class="list links-list">
<ul>
<li>
<a href="/home/" class="panel-close">
<div class="item-content">
<div class="item-media">
<i class="f7-icons ios-only">graph_square</i>
<i class="material-icons md-only">dashboard</i>
</div>
<div class="item-inner">
<div class="item-title">Home</div>
</div>
</div>
</a>
</li>
<li id="company" style="display:none;">
<a href="/company/" class="panel-close" >
<div class="item-content">
<div class="item-media">
<i class="f7-icons ios-only">home</i>
<i class="material-icons md-only">home</i>
</div>
<div class="item-inner">
<div class="item-title">Company</div>
</div>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
<!-- Top Navbar -->
<div class="navbar color-theme-green">
<div class="navbar-inner sliding">
<div class="left">
<a class="link panel-open">
<i class="f7-icons ios-only">menu</i>
<i class="material-icons md-only">menu</i>
<!--<span class="ios-only">Back</span>-->
</a>
<a class="link back">
<i class="icon icon-back"></i>
<span class="ios-only">Back</span>
</a>
</div>
<div class="title">My app</div>
</div>
</div>
<div class="view view-main"></div>
This is my config file app.js where I show and hide the elements on pageInitEvent
var $$ = Dom7;
var app = new Framework7({
// App root element
root: '#app',
// App Name
name: 'myApp',
// App id
id: 'it.myapp.myApp',
theme: 'auto',
version: '0.0.1',
cacheDuration: 0,
cache: false,
stackPages: true,
preloadPreviousPage: true,
panel: {
swipe: 'right',
swipeNoFollow: true
},
/**
* Routes
*/
routes: [
{
name: 'home',
path: '/home/',
url: './pages/home.html',
on: {
pageInit: function(e, page) {
app.navbar.show('.navbar');
page.router.clearPreviousHistory();
}
},
},
{
name: 'login',
path: '/login/',
url: './pages/login.html',
on:{
pageInit: function(){
app.navbar.hide('.navbar');
}
},
}
}
And finally this is my login.html page where I put no-navbar in orderd to hide it.
<div data-name="login" class="page no-navbar no-toolbar no-swipeback">
<div class="page-content login-screen-content ">
<!-- Login form -->
<form id="form-login">
<div class="row justify-content-center">
<div class="col-100 tablet-80 desktop-50">
<div class="card head-card-forest">
<div class="card-header">
<span></span><h2>Login</h2><span></span>
</div>
<div class="card-content card-content-padding">
<div class="row">
<div class="col-100 tablet-auto desktop-auto">
<div class="list no-hairlines-md">
<ul>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">Email</div>
<div class="item-input-wrap">
<input type="text" name="username" placeholder="Username">
<span class="input-clear-button"></span>
</div>
</div>
</li>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">Password</div>
<div class="item-input-wrap">
<input type="password" name="password" placeholder="Password">
<span class="input-clear-button"></span>
</div>
</div>
</li>
</ul>
</div>
<div class="block">
<div class="row">
<a class="col button button-fill" id="button-login" onclick="getLogin()"> Accedi </a>
</div>
</div>
</div><!--col-->
</div><!--row-->
</div><!--card-content-->
</div><!--.card-->
</div><!--.col-->
</div><!--.row-->
</form>
</div> <!-- ./ page-content -->
Best thing is hide navbar before init or while its mounted
You can try these two
1:Beforeinit
{
name: 'login',
path: '/login/',
url: './pages/login.html',
on:{
pageBeforeIn: function(){
app.navbar.hide('.navbar');
}
},
}
2:When its injected to DOM an
{
name: 'login',
path: '/login/',
url: './pages/login.html',
on:{
pageMounted: function(){
app.navbar.hide('.navbar');
}
},
}
pageInit will be triggered once required components and navbar is loaded
you can hide the panel in the login page using pageInit event
pageInit : function (e,p) { p.app.panel.left.hide() }

Categories