Binding a Component property in Vue - javascript

Good day everyone! I'm currently learning vue and I'm following a youtube tutorial on building an image carousel from scratch. Here's the code for the Image Carousel parent component:
<template>
<div class = "slides">
<div class = "slides-inner">
<div v-for= "slide in slides">
<Slide v-bind:slide= "slide"></Slide>
</div>
</div>
</div>
<script>
import Slide from './Slide';
export default{
data(){
return{
slides:[
{ src:'src/assets/slide1.jpg' },
{ src:'src/assets/slide2.jpg' },
{ src:'src/assets/slide3.jpg' },
{ src:'src/assets/slide4.jpg' },
{ src:'src/assets/slide5.jpg' }
]
}
},
components: {
Slide
}
}
</script>
<style scoped>
.slides {
align-items: center;
background-color: #666;
color: #999;
display: flex;
font-size: 1.5rem;
justify-content: center;
min-height: 10rem;
}
</style>
and here's the code for the individual image slides:
<template>
<div class="slide">
{{slide.src}}
</div>
</template>
<script>
export default {
data(){
return{}
},
props: {
slide: ['slide']
}
}
</script>
<style scoped>
</style>
The v-bind on the v-for loop on the parent Image Carousel component is supposed to bind the slide.src property to the current slide being looped so that it will display the image in the browser but what I'm getting is a blank browser screen and an error that says the right value of the operator at v-bind is not an object although the tutorial I'm following works exactly as it should with this same code so I'm wondering what I'm doing wrong.

In your slide component, it should be
export default {
data(){
return{}
},
props: {
slide: Object
}
}
You can check valid props type in Vue document

Please also see the Vue Style Guide as prop definitions should be as detailed as possible. An Essential Requirement by the creators of Vue. See Vue Style Guide.

Related

onShow Lifecycle Function Is Not Triggered in QuickApp?

I have a quick app that im writing which contains a quick app page that references only a single custom element through the router.push API, the onShow lifecycle function for that page cannot be triggered.
<import name="listone" src="./aa.ux"></import>
<template>
<!-- The template can contain only one root node. -->
<listone></listone>
</template>
<script>
import prompt from '#system.prompt'
export default {
private: {
},
onInit: function() {
},
onShow() {
console.log('Enter a string whatever you like.');
prompt.showToast({
message: 'Enter a string whatever you like.'
})
}, // This function cannot be triggered.
}
</script>
<style>
.demo-page {
flex-direction: column;
justify-content: center;
align-items: center;
}
.title {
font-size: 40px;
text-align: center;
}
</style>
And my aa.ux file
<template>
<div class="container">
<text> Enter some words.</text>
<text>Enter some words.</text>
<text>Enter some words.</text>
<text>Enter some words.</text>
</div>
</template>
<style>
.container {
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #00fa9a;
}
</style>
<script>
module.exports = {
data: {
},
onInit() {
},
}
</script>
How can i get the onShow function to trigger in this situation?
I have gotten to the 'root' of the issue, the quick app loader does not trigger the onShow lifecycle function if the root node of the page is a custom element. However, the function can be triggered for a subelement. SO the way to get round this for me was to add an extra div element like:
<template>
<!-- The template can contain only one root node. -->
<div>
<listone></listone>
</div>
</template>

Hiding Popover on internal click

I'm currently using Vue-PopperJS, and have pretty much set it up as they have on the attached link with some slight changes:
<template>
<Popper
ref="popover"
trigger="clickToToggle"
:options="{
placement: position,
}"
>
<slot
slot="reference"
name="activator"
/>
<div class="base-dropdown--dropdown popper">
<slot name="popover" />
</div>
</Popper>
</template>
<script>
import Popper from 'vue-popperjs'
import 'vue-popperjs/dist/vue-popper.css'
export default {
name: 'BaseDropdown',
components: {
Popper
},
props: {
position: {
type: String,
default: 'bottom'
}
}
}
</script>
<style scoped lang="sass">
.base-dropdown
&--dropdown
min-width: 180px
#apply rounded-large shadow-sm
</style>
And for the items inside the popover we created another component like so:
<template>
<div
class="base-dropdown-item"
:class="getDropdownItemClass"
#click="$emit('click')"
>
<slot />
</div>
</template>
<script>
export default {
name: 'BaseDropdownItem',
props: {
hoverable: {
type: Boolean,
required: false
}
},
computed: {
getDropdownItemClass () {
if (this.hoverable) return ['hover:bg-blue']
return []
}
}
}
</script>
<style scoped lang="sass">
.base-dropdown-item
text-overflow: ellipsis
padding: 12px 0 12px 12px
#apply cursor-pointer body-3 flex items-center overflow-hidden text-grey-800 transition-all whitespace-nowrap
&:hover
#apply text-black
</style>
My question is, say I click on the popover content (ie, a button that does something), how can I trigger it to close the popover too?
I know there is an event to hide it but I'm not sure how to use it.
Should you need more information please don't hesitate to ask!
Not sure how 'efficient' this solution is. However, Chase DeAnda's comment gave me an idea for an elegant solution.
I ended up using the EventBus that would $emit('close-popver'). This emit would be from whatever (in this case a <BaseDropDownItem /> component) that calls this method on a #click.
methods: {
handleClick() {
this.$emit('click')
EventBus.$emit('close-popover')
}
}
And to close the popover:
closePopover(){
const { popover } = this.$refs
popover.doClose()
}

Why height: 0 can not work in css definition

In my project, I use vue.js 2, and i have an img component.
Here is code of it:
<template>
<div class="banner">
<img class="banner-img" :src="bannerImg"/>
</div>
</template>
<script>
export default {
name: 'DetailBanner',
props: {
sightName: String,
bannerImg: String,
gallaryImgs: Array
}
}
</script>
<style lang="stylus" scoped>
.banner
position: relative
overflow: hidden
height: 0
padding-bottom: 55%
.banner-img
width: 100%
The url of img is :
http://img1.qunarzz.com/sight/p0/201404/23/04b92c99462687fa1ba45c1b5ba4ad77.jpg_600x330_bf9c4904.jpg
Here i don't want to display this img, so i set height:0 in CSS.
But unlucky, It fails. I have tested for removing height: 0, and it shows all the same.
why height: 0 can not work, who can help me?
You could take advantage of Vue.js and use v-if to show/hide your image as follow :
<template>
<div class="banner" v-if="showImg">
<img class="banner-img" :src="bannerImg"/>
</div>
</template>
<script>
export default {
name: 'DetailBanner',
props: {
sightName: String,
bannerImg: String,
gallaryImgs: Array
},
data(){
return{
showImg:false
}
}
}
</script>
you could put showImg in your props, by this way you could change the image state using only Vue.js and avoid struggling with CSS

Dynamic image is not loaded via :src

I am working on a simple Vue app, using vue-cli and webpack for that purpose.
So basicly i have 2 components, a parent and a child component ~
like this:
<template>
<div class="triPeaks__wrapper">
<div class="triPeaks">
<tri-tower class="tower"></tri-tower>
<tri-tower class="tower"></tri-tower>
<tri-tower class="tower"></tri-tower>
</div>
<div class="triPeaks__line">
<tower-line :towerLine="towerLineCards" />
</div>
<tri-pack />
</div>
</template>
the towerLineCards is the important thing there, it is a prop that is passed to the tower-line component, it is basicly a array with 10 elements, it is a array with 10 numbers that are shuffled, so it can be something like that:
[1,5,2,6,8,9,16,25,40,32]
this array is create via beforeMount on the lifecycle.
On the child component:
<template>
<div class="towerLine-wrapper">
<div class="towerLine">
<img v-for="index in 10" :key="index" class="towerLine__image" :src="getImage(index)" alt="">
</div>
</div>
</template>
<script>
export default {
props: {
towerLine: {
type: Array,
required: true
}
},
method: {
getImage (index) {
return '#/assets/images/cards/1.png'
}
}
}
</script>
<style lang="scss">
.towerLine {
display: flex;
position: relative;
top: -90px;
left: -40px;
&__image {
width: 80px;
height: 100px;
&:not(:first-child) {
margin-left: 3px;
}
}
}
</style>
the issue is with the :src image that i am returning via the getImage(), this way it is not working. If i change to just src it works just fine, i did this way just to test, because the number in the path should be dynamic when i got this to work.
What is wrong with this approach? any help?
Thanks
Firstly, you should use a computed property instead of a method for getImage().
And to solve the other problem, you could add require(YOUR_IMAGE_PATH) when you call your specific image or put it inside /static/your_image.png instead of #/assets/images/cards/1.png.

VueJS error compiling template

I just made my first project with VueJS and Vue-loader.
So I made my first component to show a simple message, it works fine when I make one message, but I get an error when I make multiple messages:
(Emitted value instead of an instance of Error)
Error compiling template:
<message>This is a small message!</message>
<message>Another one</message>
- Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
This is my code. I'm very new to this and I can't figure out what's wrong.
App.vue
<template>
<message>This is a small message!</message>
<message>Another one</message>
</template>
<script>
import Message from './Components/Message.vue';
export default {
name: 'app',
components: {
Message,
},
data () {
return {
}
}
}
</script>
Message.Vue
<template>
<div class="box">
<p>
<slot></slot>
</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
.box { background-color: #e3e3e3; padding: 10px; border: 1px solid #c5c5c5; margin-bottom: 1em;}
</style>
I hope somebody can help!
The error is pretty self-explanatory. You should have only one root element in each component. So just pack everything in a div.
<template>
<div>
<message>This is a small message!</message>
<message>Another one</message>
</div>
</template>

Categories