My component is simple:
<template>
<btn :color="color" @click="toggleColor">{{btnmsg}}</btn>
</template>
<script>
import { Btn } from 'chico'
export default {
name: 'AButton',
components: {
Btn
},
data() {
return {
btnmsg: 'Legia pany',
colors: [
'blue', 'black', 'green',
'orange', 'teal', 'cyan',
'yellow', 'white'
],
color: 'red'
}
},
methods: {
toggleColor() {
this.color = this.colors[Math.floor(Math.random() * Math.floor(this.colors.length))];
}
}
}
</script>
The <Btn>
from the ChicoFamily goes something like this:
<template>
<button :is="tag" :class="[className, {'active': active}]" :type="type" :role="role">
<slot></slot>
</button>
</template>
<script>
import classNames from 'classnames';
export default {
props: {
tag: {
type: String,
default: "button"
},
color: {
type: String,
default: "default"
},
//...it takes a lot of props...
},
data() {
return {
className: classNames(
this.floating ? 'btn-floating' : 'btn',
this.outline ? 'btn-outline-' + this.outline : this.flat ? 'btn-flat' : this.transparent ? '' : 'btn-' + this.color,
//...classes derived from these props...
),
};
}
}
</script>
It's a button that, when clicked, should change its color. Clicking it indeed changes the prop passed, but does not re-render the button in the new color.
Why does passing a different prop not re-render the button?
The <Btn>
takes its color from Bootstrap classes deriving from the prop. Could it be that the Btn gets the proper prop, but the className
mechanic does not catch up?
This isn't a re-rendering problem– the component is indeed re-rendering when the prop changes. The problem is that the re-render does it no good, because you set the color as an initial value in data
, and not as a computed
property that gets re-evaluates when data changes.
The way you did it, the className
will be set once when the instance will is created, and never again.
In order to make the className
re-evaluate each time you change one of the props passed in, you will have to make a computed
property out of it, like this:
Btn component:
export default {
props: {
[...]
},
computed: {
className() {
return classNames(
this.floating ? 'btn-floating' : 'btn',
this.outline ? 'btn-outline-' + this.outline : this.flat ? 'btn-flat' : this.transparent ? '' : 'btn-' + this.color
);
},
},
}