How to pass Boolean props to another component in vuejs - javascript

I have two components: component A and Component B. In the component A, I have a props called hasBorder with Boolean type and when i call component A in the component B, I passed value to a props component of component A, I have an error.
html component A:
<div> <img src="path" :style="hasBorder ? 'border:5px;': ''"/></div>
js component A:
Vue.component('compA', {
props: {
hasBorder:{
type:Boolean,
default:false
}
}
});
html component B:
<div> My image : <compA has-border="myStyle"></compA></div>
js component B:
Vue.component('compB', {
data: {
return {
myStyle : { type:Boolean, default :true}
}
}
});
I have this error "Invalid prop:type check failed for prop hasBorder. Expected Boolean, got String with value "myStyle".
How can i fix this error please

You need to bind your props with v-bind: or : in order to pass data. Data property needs to be a function that returns object. Please take a look at snippet:
const app = Vue.createApp({
data() {
return {
myStyle: true,
myPath: 'https://picsum.photos/100'
};
},
})
app.component('compA', {
template: `
<div><img :src="path" :style="hasBorder ? 'border: 5px solid turquoise;': ''"/></div>
`,
props: {
hasBorder:{
type:Boolean,
default:false
},
path: {
type: String,
default: ''
}
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div> My image : <comp-a :has-border="myStyle" :path="myPath"></comp-a></div>
</div>

You expect bool value but you are trying to send an object.
Try this
Vue.component('compB', {
data: {
return {
myStyle : true
}
}
});
And use v-bind
<div> My image : <compA v-bind:has-border="myStyle"></compA></div>

Related

Class as function in functional component - Vue

I am writing a simple functional component in vuejs. Currently stuck at a situation where I want to add conditional css class based on the props passed to it.
However the below doesn't work as expected and I am wondering what wrong am I doing here.
<script>
export default {
name: "BasePill",
functional: true,
props: {
variant: String
},
render(createElement, { children, props }) {
const componentData = {
staticClass: "text-sm text-center"
class: function() {
if (props.variant === 'secondary') {
return 'bg-secondary'
}
return 'bg-primary'
}
};
return createElement("span", componentData, children);
},
};
</script>
The class property cannot be a function, it needs to be a string/array/object.
Do this instead:
const componentData = {
staticClass: 'text-sm text-center',
class: props.variant === 'secondary' ? 'bg-secondary' : 'bg-primary',
};

Prop is possibly undefined error in Vue 3 setup

The console.log('test',props.list) works well.
But props.list.map doesn't work.
Here is the error message.
And here is the code of the component
How can I fix this error?
<template>
<div class="row">
<div v-for="column in columnList" :key="column.id" class="col-4 mb-4">
<div class="card-body">
<div class="card h-100 shadow-sm" >
<img :src="column.avatar" :alt="column.title">
<h5>{{column.title}}</h5>
<p>{{column.description}}</p>
enter
</div>
</div>
</div>
</div>
</template>
<script lang='ts'>
import { computed, defineComponent, PropType } from 'vue'
export interface ColumnProps{
id: number;
title: string;
avatar?: string;
description: string;
}
export default defineComponent({
name: 'ColumnList',
props: {
list: {
type: Array as PropType<ColumnProps[]>,
require: true
}
},
setup (props) {
const columnList = computed(() => {
console.log('test',props.list)
return props.list.map(column => {
if (!column.avatar) {
column.avatar = require('../assets/default_avatar.jpg')
}
return column
})
})
return { columnList }
}
})
</script>
I think, the only bit missing is a typo in the required option.
Change
props: {
list: {
type: Array as PropType<ColumnProps[]>,
require: true
}
},
to
props: {
list: {
type: Array as PropType<ColumnProps[]>,
required: true // <----- CHANGE TO "required"
}
},
I'm guessing the list prop is populated by an async call. If so, the computed runs at least once before props.list is defined. When it's undefined, it has no .map method.
Provide for that situation by returning an empty array:
setup (props) {
const columnList = computed(() => {
if (!props.list) return []; // ✅ Return an empty array if undefined
return props.list.map(column => {
if (!column.avatar) {
column.avatar = require('../assets/default_avatar.jpg')
}
return column
})
})
return { columnList }
}
It's a typescript error (TS2532). The type of props is unknown. You need to specify a type for the props parameter, like this:
interface Props {
list: ColumnProps[];
}
setup(props: Props) {
...
}
Your current props definitions only tell Vue what props and types to expect, but not Typescript
Your error comes from typescript.
This is because of the way vue defines your props for typescript.
If you had required: true, then you state it cannot not be undefined, else it may.
The accepted answer is conceptually wrong, but it works because the you check for undefined before accessing the value if (!props.list) ... and the compiler is smart enough to know that.
If you know it will be defined and do not want to use required: true, you can tell it the compiler by writing props.list!.map

Pass a props in the ":to" attribute of a router link in Vue.js

I'm having an issue to create a router-link in vue and passing it a route name as a props...
What I want to do basically is this :
<template>
<div>
<router-link :to="myProps">Login</router-link>
</div>
</template>
<script>
export default {
name: componentName,
props: {
myProps: {
type: String,
default: '{ name: login }'
}
}
}
</script>
Login is of course difined in my router. But as I give the route as a props, I get redirected to /%7B%20name:%20'login'%20%7D. Do you know of any trick to get around this ?
What you get from the default value is a string, but you need an object. Try in this way:
props: {
myProps: {
type: Object,
default: () => ({name: 'login'})
}
}
Here's more about props default value: https://v2.vuejs.org/v2/guide/components-props.html#Prop-Validation

v-if is not working in my child component

I am trying to show a span whenever v-if is equal to true in my child component. Could anyone advice what I did wrong. Currently, I have no idea what I did incorrectly.
Child Component
const cardsTemplate = {
template:
`
<fieldset v-if="show.seach_checkboxes">
<span>HELLO WORLD</span>
</fieldset>
`,
props: ['js_local'],
data() {
return {
show:{
search_checkboxes : {
type: Boolean,
default: true,
}
}
}
},
methods :{
change_boolean : function(reverse_boolean){
this.show[reverse_boolean] = !this.show[reverse_boolean]
console.log(this.show)
},
show_search_template: function(){
this.change_boolean('search_checkboxes')
},
get_search_template : function(){
$.post(this.js_local.ajaxurl,
{action : 'get_search_templates'}
).done((data)=>{
this.name = JSON.parse(data)
}).fail((error)=>{
console.log(error)
})
},
}
}
It looks like you're trying to use data() with type checking, the same way props is used. Try this:
data() {
return {
show: {
search_checkboxes: true
}
}
}
Also, in your template HTML, you've misspelled search_checkboxes, it's missing an "r".
<fieldset v-if="show.seach_checkboxes">
^^^

Call great grand children component method

I got a set of nested components as follows in Vue 2.2.1:
<Root>
<VForm>
<Accordion>
<Panel>
<Stripe ref="stripe">
And I need to call a method getToken on the Stripe component when the form is submitted. On my <VForm> component I have the following template.
<template>
<form :method="method" :action="action" :class="classes" :autocomplete="autocomplete" #submit.prevent="submit">
<slot></slot>
</form>
</template>
<script>
export default {
props: {
method: {
type: String,
default: 'POST'
},
action: {
required: true,
type: String
},
classes: {
type: String
},
autocomplete: {
type: String,
default: 'on'
}
},
methods: {
submit(){
this.$refs.stripe.getToken
}
}
}
</script>
But I get Uncaught TypeError: Cannot read property 'getToken' of undefined. I also tried it by emitting an event at the <v-form> level but, if i'm not mistaken, it is my understanding that the events flow from child to parent, so that didn't work.
How can I trigger stripe.getToken on <v-form> submit?
You could use a bus.
const bus = new Vue();
Vue.component("parent", {
methods:{
triggerStripe(){
bus.$emit('get-token');
}
}
})
Vue.component("stripe",{
mounted(){
bus.$on('get-token', () => this.getToken());
}
})

Categories