I'm trying to implement a tabbed reusable component in vueJs but I'm getting an error that a particular component is not defined. Below are both components
//TabComponent
<template>
<div>
<div class="row">
<div class="col-lg-12 col-xl-12">
<div class="card-box">
<ul class="nav nav-tabs nav-bordered">
<li v-for="tab in tabs" :key="tab" class="nav-item">
{{tab}}
</li>
</ul>
<div class="tab-content">
<component :is="selectedComponent"></component>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'TabComponent',
props: [ selectedComponent, tabs ] //The error is coming from this line
}
</script>
I have imported it to this component and currently it shows the error
Uncaught ReferenceError: selectedComponent is not defined
//Entitlements component
<template>
<div>
<tab-component :tabs="tabs" :selectedComponent="selectedComponent" />
</div>
</template>
<script>
import TabComponent from "../../../components/TabComponent";
import List from "./Entitlements/List";
import MyEntitlements from "./Entitlements/MyEntitlements";
export default {
name: 'Entitlements',
components: {List, MyEntitlements, TabComponent},
data(){
return{
tabs: ['List', 'MyEntitlements'],
selectedComponent: 'List',
}
}
}
</script>
HTML attribute names are case-insensitive, so browsers will interpret
any uppercase characters as lowercase. That means when you’re using
in-DOM templates, camelCased prop names need to use their kebab-cased
(hyphen-delimited) equivalents (source)
Try with:
<tab-component :tabs="tabs" :selected-component="selectedComponent" />
Edit:
If you define props as an array, change the list with strings (see "Prop types" here):
props: [ 'selectedComponent', 'tabs' ]
Related
I was trying to implement a reusable card component, so I printed them out inside variable properties that is changed image by image
This is my code. As for title, it works perfectly. I implemented it many times, so my issue is different. I also added this props' text inside mustaches, so I can change link and image out of my card, but it doesn't work, so I need your help. I might just not understand how text interpolation works. But I think that vue supports the way to create reusable cards within a component
<template>
<RouterLink class="card" to="{{ link }}">
<div class="card__background" style="background-image: url({{ image }})"></div>
<div class="card__content">
<h3 class="card__heading">{{ title }}</h3>
</div>
</RouterLink>
</template>
<script>
import { RouterLink } from 'vue-router';
export default {
props: ['link', 'image', 'title'],
created() {
console.log(this.link)
console.log(this.image)
console.log(this.title)
},
}
</script>
I think you need to use the v-bind directive. This directive allows you to bind the value of an HTML attribute to a dynamic expression.
Here's how you can modify your code to use the v-bind directive:
<template>
<RouterLink class="card" v-bind:to="link">
<div class="card__background" v-bind:style="{ backgroundImage: `url(${image})`
}"></div>
<div class="card__content">
<h3 class="card__heading">{{ title }}</h3>
</div>
</RouterLink>
</template>
<script>
import { RouterLink } from 'vue-router';
export default {
props: ['link', 'image', 'title'],
created() {
console.log(this.link)
console.log(this.image)
console.log(this.title)
}
}
</script>
I am getting html string from api server to show the data in Vue component.
However, I cannot convert br tag, nbsp;, or such strings which is in the actual response from the api server.
What I want to see:
Hello
World
What I am seeing in the screen right now:
Hello'htmlbrtag'World
Is there any way I could solve this problem?
<template>
<div class="swiper-slide">
<div class="sw-lead-box">
<span class="sw-title">{{ banner.title }}</span>
<span class="sw-tags">{{ banner.content }}</span>
</div>
<div class="img__shadow"></div>
<img class="sw-bg" src="../../static/images/main/m-swiper-bg1.png" alt="" />
</div>
</template>
<script>
export default {
props: {
banner: {
type: Object,
required: true,
},
},
};
</script>
<style></style>
banner.title and banner.content are the items that correspond to the issues I mentioned above.
Is there any Jquery's html() function for vue?
I am new to vueJS.
What I want to do is passing parameters to a component, depending on the selection of the routes. Here is my App.vue:
<template>
<div id="main">
<header>
<h1 style="color:red">{{msg}}</h1>
</header>
<div>
<aside class="sidebar">
<router-link v-for="el in this.$router.options.routes" :to="el">
{{el.name}}
</router-link>
</aside>
<SubMenu></SubMenu>
<div class="content">
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import SubMenu from './components/SubMenu.vue'
export default {
components: {
'SubMenu': SubMenu
},
data() {
return {
msg: 'Welcome to Your Vue.js App' }
}
}
</script>
<style>
#import 'style.css';
#import 'grid.css';
</style>
and the SubMenu component I would like to make dynamic:
<template>
<div>
something dynamic
</div>
</template>
How can I pass some parameters to use in the component?
thank you
Your App.vue can be like this:
<template>
<div id="main">
<header>
<h1 style="color:red">{{msg}}</h1>
</header>
<div>
<aside class="sidebar">
<router-link v-for="el in this.$router.options.routes" :to="el">
{{el.name}}
</router-link>
</aside>
<SubMenu :menuTitle="subMenuTitle"></SubMenu>
<div class="content">
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import SubMenu from './components/SubMenu.vue';
export default {
components: {
SubMenu
},
data() {
return {
subMenuTitle: "This is the sub menu",
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<style>
#import 'style.css';
#import 'grid.css';
</style>
The SubMenu.vue component could be like this:
<template>
<div>
<h2>{{ menuTitle }}</h2>
something dynamic
</div>
</template>
<script>
export default {
name: "SubMenu",
props: {
menuTitle: String,
}
}
</script>
In the SubMenu component that was used in App.vue, notice the colon that appears before the menuTitle attribute. When you do that before an attribute, the value of that attribute would be evaluated by Vue and passed to the component. You can pass literal Javascript expressions or items in your App.vue component.
In the SubMenu component, you can use the props in whatever way you can. If the prop's value is an array, you can use the v-for directive with it to create a list of items in the SubMenu.
Welcome to SO,
In Vue.js passing parameters to components is called "Props"
You can pass props to your SubMenu like below
<SubMenu :id="12345" someText="Some Text About Something" :dataArray="[1,2,3,4,5]" />
then inside your SubMenu component you can define Prop Types as below
props: ['dataArray']
or
props: {
dataArray: {
type: Array,
default: []
}
}
After that you can use the data you passed to your liking
You can also read up on this Vue Documentation regarding the Props, which has much more detailed explanations about various Props related stuff and sample code
Ok many thanks to both.
But what if I would like to pass something that depends on the voices in router-link? I mean, router-link prints a menu with 4 voices...what if I would like a behavior like this:
click on voice1 in router-link ---> pass this object ['input1', 'input2'] to SubMenu
click on voice2 in router-link ---> pass this other object ['input3', 'input4', 'input5'] to SubMenu
and so on.
thanks again :)
Im super new to Vue.
i have a Vue-CLI app, which have a navbar and content.
Navbar is common to all pages, but i want to customize in each page whit some additional content.
Example:
Common-> home | about
View home -> home | about | your are in view home
View about -> home | about | your are in view about
router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
import NavBar from '#/components/NavBar.vue';
Vue.use(VueRouter);
Vue.component('nav-bar', NavBar);
//...
components/navbar.vue
<template>
<div>
<b-nav-item to="/">home</b-nav-item>
<b-nav-item to="/about">about</b-nav-item>
{{customContent}}
</div>
</template>
<script>
export default {
name: 'NavBar',
props: {
customContent: {
type: String,
default: 'default Content',
},
},
};
</script>
App.vue
<template>
<div id="app">
<nav-bar />
<div class="container-fluid">
<router-view />
</div>
</div>
</template>
views/home.vue
<template>
<div class="row">
<div class="col-12">
<image-card :images="images"/>
</div>
</div>
</template>
<script>
//how can i customize here the navbar by adding for example 'your are in view home'???
</script>
Thanks so much!
There are a few ways in which you can solve this problem. I'll list two of them.
1. Update NavBar by $route
In this approach, the NavBar component already contains all of the possible combinations, and will display the relevant portion(s) depending on what $route contains.
Here's some pseudo code:
navbar.vue
<template>
<div class="navbar">
<div class="navbar-left>
APPNAME
</div>
<div v-if="name === 'landing'">
...
</div>
<div v-else-if="name === 'room'">
...
</div>
</div>
</template>
App.vue
<template>
<div id="app">
<NavBar :name="$route.name"/>
<main>
<router-view/>
</main>
</div>
</template>
In this example, the NavBar component is very rigid, and doesn't really lend itself to much reuse. However, it does encapsulate all the relevant code relating to the nav bar.
2. Extensible NavBar with slots
In this approach, the NavBar only provides the bare-minimum to create a nav bar. The rest of the route-specific elements are to be filled in by the views.
navbar.vue
<template>
<div class="navbar">
<div class="navbar-left">
<div class="navbar-brand">
APPNAME
</div>
<slot name="left"></slot>
</div>
<div class="navbar-right">
<slot name="right"></slot>
</div>
</div>
</template>
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
landing.vue
<template>
<div>
<header>
<NavBar>
<template slot="right">
<span>
<div class="navbar-item">
<div class="buttons">
<button class="button" #click="...">Start Watching</button>
</div>
</div>
</span>
</template>
</NavBar>
</header>
<main>
...
</main>
</div>
</template>
This approach has a bit of repetition in terms of DOM elements, but gives you an extremely flexible NavBar that can be customized by each view.
The approach you want to use depends on what is important to you.
If strict encapsulation is what you want, then you may want to use approach 1, as all of the NavBar-related code is contained within a single file.
However, if you believe that there is a potential for reuse, or if you would like all view-related code to live in one place, then it makes sense to use slots instead and extend the NavBar as required by each view.
I use a breadcrumb to achieve a similar thing. Just an idea but Vue router allows you to add meta data to the current route which you always have access to
router.js
path: '/add',
name: 'add',
component: () => import(/* webpackChunkName: "add" */ '../../views/Add.vue'),
meta: {
breadCrumb: [
{ name: 'Add New' }
]
},
Notice the meta object attached to the route.. this will be used to describe the current view.
Breadcrumb.vue component
<template>
<div class="breadcrumb">
<ul class="d-flex m-0 p-0"
<li
v-for="(breadcrumb, idx) in breadcrumbList"
:key="idx">
{{ breadcrumb.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Breadcrumb',
data () {
return {
breadcrumbList: []
}
},
mounted () { this.updateList() },
watch: { '$route' () { this.updateList() } },
methods: {
routeTo (pRouteTo) {
if (this.breadcrumbList[pRouteTo].link) this.$router.push(this.breadcrumbList[pRouteTo].link)
},
updateList () { this.breadcrumbList = this.$route.meta.breadCrumb },
formatPath(path) {
const newPath = path.replace(/\//g, " > ")
return newPath
}
}
}
</script>
And then you can import the breadcrumb into your navbar or where ever you would like to place it
<Breadcrumb class="breadcrumb" />
import Breadcrumb from '#/components/Breadcrumb.vue'
components: {Breadcrumb}
So basically the breadcrumb will always watch your current route and change the data based on the meta data you provide in your router.js file
You can access to router name like this:
<div v-if="this.$route.name == 'home'">
<HeaderTransparent />
</div>
<div v-else>
<HeaderWhite />
</div>
I'm fairly new to Vue so this may be obvious, but I must be missing something. I keep getting the error: [Vue warn]: Missing required prop: "productInfo" in my .vue file. It says its found in ProductSlider.vue.
ProductSlider.vue
<template>
<div
id="recommendedProducts">
<h2>{{ params.headerText }}</h2>
<div
class="wrapper">
<div class="carousel-view">
<carousel
:navigation-enabled="true"
:min-swipe-distance="1"
:per-page="5"
navigation-next-label="<i class='fas fa-3x fa-angle-right'></i>"
navigation-prev-label="<i class='fas fa-3x fa-angle-left'></i>">
<slide
v-for="product in products"
:key="product.id">
<Product
:id="product.id"
:product-info="product"/>
</slide>
</carousel>
</div>
</div>
</div>
</template>
<script>
import Slider from './Slider'
import Product from './Product'
import {mapState, mapGetters} from 'vuex'
import axios from 'axios';
export default {
name: "Slider",
components: {
Product
},
props: {
productInfo: {
type: Object,
required: true
}
},
I chopped off the end of the ProductSlider code because the rest is very long and irrelevant.
And then here is my Product.vue:
<template>
<Product>
<div class="img-container text-center">
<a
:href="productInfo.href"
class="handCursor"
tabindex="0">
<img
v-if="productInfo.imgOverlay"
:src="productInfo.imgOverlayPath"
:alt="productInfo.title"
:aria-label="productInfo.title"
border="0"
tabindex="-1">
<img
:src="productInfo.imgURL"
:alt="productInfo.title">
</a>
</div>
<h4 class="itemTitle">{{ productInfo.title }}</h4>
<div class="price-div">
<div class="allPriceDescriptionPage">{{ productInfo.price }}</div>
</div>
<a
href="#"
tabindex="0"
name="instantadd">
<div class="btn_CA_Search buttonSearch gradient"> Add to Cart</div>
</a>
</Product>
</template>
<script>
export default {
name: "Product",
props: {
productInfo: {
type: Object,
required: true,
},
},
}
</script>
I have productInfo in the props so I'm not sure why I keep getting this error.
I think you confused props and the child component's props, when you have:
<Product
:id="product.id"
:product-info="product"/>
You have a prop productInfo defined in the child component Product, not in the component ProductSlider itself, and if you define prop productInfo in ProductSlider, then you have to pass it down from the parent component, that is you need to have <ProductSlider :product-info="..."/> whenever ProductSlider is used.
Notice <Product :product-info="product"/> doesn't mean you are using the value of productInfo, product-info is the name of prop that's defined in Product component.
I think a fair analogy to use is if you think of your component as a function, props are function parameters, and required function parameters need to provided when they are called.
For your case, to eliminate the error, you can simply remove the productInfo prop from ProductSlider component since it's not used in that component.