I am passing in a 'type' prop to my component to use as a BEM modifier.
<div class="badge badge--{{this.$props.type}}">
However when I try and concatenate the class I get an error. How do I achieve this?
A cleaner way to do it is to create a computed property :
computed: {
badgeClasses() {
return `badge badge--${this.type}`;
},
},
And then bind it in your HTML :
<div :class="badgeClasses">
But you can also just bind the property, as you tried, but with a backquote instead of a simple quote :
<div class="`badge badge--${type}`">
Related
I have 2 themes: 'light-theme', 'dark-theme'
I would like to set the <html class=""> according to a value i have in my vuex store. Like darkMode: true
How can i set the <html> class reactively like that?
(using vue3)
You can use simple javascript for it.
Just add a button or toggle for theme change like:
<button #click="changeTheme">Change Theme</button>
and inside this component add changeTheme method inside methods:
document.getElementsByTagName("html")[0].setAttribute( 'class', 'newThemeClass' );
Or just add watcher to your store value and change according to it:
computed:{
...mapGetters(["yourGetterName"])
},
watch: {
darkMode(value) {
document.getElementsByTagName("html")[0].setAttribute( 'class', value );
},
}
According to Vue docs, there are following ways to do this.
1.Binding to Objects
<div :class="{ 'active-class': isActive }"></div>
The above syntax means the presence of the 'active-class' class will be determined by the truthiness of the data property isActive.
2.Binding to Arrays
<div :class="[isActive ? activeClass : '', errorClass]"></div>
This will always apply errorClass, but activeClass will only be applied when isActive is truthy.
I have html element:
<div style="grid-column: span 1">
I would like to use function to determine span size:
I try something like this, but it doesn't render.
:style="{ 'grid-column: span': getColumnSize('string') }"
what is correct syntax?
use computed method. in computed method you can write a function that return your style as an object. then use it in your html.
<div :style="getColumnSize"></div>
computed: {
getColumnSize() {
return {
gridColumn: 'span 1'
}
}
}
note: you should use camel case.
i would store the value of span in data then place the value in style like this
<div :style="`grid-column : span ${spanValue}`"> new div with grid</div>
you can do like this
<div :style="{ 'grid-column': `span ${getColumnSize('string')}` }"></div>
I looked at one of the answers and tried to apply it, but then I realized it didn't work and I tried numerous things like using Vuex to calculate the years before I used it, but nothing worked.
Generate Years from 1900 to current year with VueJS
Property or method "value" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
Like I said, I tried using Vuex and trying to call it on the beforeCreate hook, but it didn't work.
<template>
<md-field md-clearable>
<label for="year">Year</label>
<md-select v-model="year" name="year" id="year">
<md-option :v-for="value in values" value="value">
{{ value }}
</md-option>
</md-select>
</md-field>
</template>
<script>
export default {
name: 'Component',
data () {
year: null
},
computed: {
values () {
const year = new Date().getFullYear()
return Array.from({length: year - 1900}, (value, index) => 1901 + index)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
</style>
I am expecting the dropdown to have years value instead of it being null and giving an error message. I also tried to rename the values, but it doesn't have to do anything with that. It's a really weird bug. I am seriously wondering if it's caused by vue.js itself.
Your data property should return values:
data () {
return {
year: null
}
},
And your v-for shouldn't have : in front:
<option v-for="value in values" >
{{ value }}
</option>
Fix those and it should be working.
The reason behind the previous error is that you most probably forgot to define the prop XXX in the data object of your Vue application:
var application = new Vue({
el: '#app',
data: {
// The prop XXX is not defined here, so add it ;)
}
});
There are two mistakes in your code.
First one is:
<md-option v-for="(val,index) in values" :key="index" :value="val">
{{ value }}
</md-option>
You need to make the value attribute reactive to consider the dynamic values from the v-for loop.
Always use :key attribute while using v-for.
There should not be : as prefix of v-for.
Try to keep variable names different from the attributes for better code understanding.
Second one is:
data () {
return {
year: null
}
},
You were missing to return in the data() object.
There are two issue in your code:
Your are not using data properties correctly. You should return values inside data like this:
data () {
return {
year: null
}
}
You are using a : before v-for which is wrong and I think that's why you are facing the issue. Just remove that :
Hope it helps !!
I have a big problem with VueJS and Element UI https://element.eleme.io/#/en-US/component/input#autocomplete-attributes
I use the AutoComplete Component, and i want that I click on the input (onFocus Event), my suggestions re appear
<el-autocomplete
id="inputID"
name="inputName"
class="inputClass"
v-model="inputModel"
:fetch-suggestions="querySearchInput"
placeholder= "Select an Input"
ref="inputReference"
value-key="id"
v-loading="inputLoader"
:value="inputValue"
#select="onChangeInput"
#focus="onFocusInput"
#clear="onClearInput"
clearable
>
<!-- Slot : Override Component Suggestions -->
<template slot-scope="{item}" v-if="item.id">
{{ item.id }} - {{ item.name }}
</template>
</el-autocomplete>
on my onFocus or onClear i used :
this.inputModel = "";
this.inputValue = ""
But it does not reset my suggestions.. :/
The only way for me is to use :
this.$refs.inputReference.value = "";
But it's not a best pratice I have a message : " vue.esm.js?efeb:591 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value" "
I use a :value and a v-model on my component because i stock an ID but i display a label with i18n, isn't important
VERY THANKS YOU
I think it's because the AutoComplete Component includes a InputComponent, and i'm not a pro with the cascading prop on VueJS..
Thanks.
Just do like it says. Do not mutate props. If you need to change some date from props, save it to local component data and modify it
props: {
foo: {
type: number,
requred: true
}
},
...
data () {
return {
localFoo: this.foo
}
}
I have a lot of forms to create in a web app I'm working on, for which I'm using Vue, so I've been trying to create a generic input component I can use throughout. I'm using Bootstrap grids, so the idea is that I should be able to pass the component a number of columns to take up, a label, a name and a property to use as the v-model. I'm kind of getting there, I think, but I'm running into a problem with mutating props - [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "model"
(found in component ).
Here's the template (in simplified form):
<template id="field">
<div v-bind:class="colsClass">
<div class='form-group form-group-sm'>
<label v-bind:for="name">{{labelText}}</label>
<input v-bind:id='name' ref="input" class='form-control' v-bind:name='name' v-model='model'/>
</div>
</div>
And here's the (again simplified) JS:
Vue.component('field', {
template: '#field',
props: ['cols','label','group','name','model'],
computed:{
colsClass:function(){
return "col-xs-"+this.cols
}
,
labelText:function(){
if(this.label) {
return this.label
} else {
return _.startCase(this.name);
}
}
}
});
This is used from within another 'edit-product' component, like this:
<field :cols="8" name="name" :model="product.name"></field>
This displays OK, but throws the error (or more accurately, warning), when I edit the value of the field. So what am I doing wrong?
Actually, the solution I've gone for is rather simpler than the one suggested above, very simple in fact, taken from https://forum-archive.vuejs.org/topic/4468/trying-to-understand-v-model-on-custom-components/9.
I don't want the 'model' prop, I have a 'value' one instead, so the JS is changed to this:
Vue.component('field', {
template: '#field',
props: ['cols','label','group','name','value'],
computed:{
colsClass:function(){
return "col-xs-"+this.cols
}
,
labelText:function(){
if(this.label) {
return this.label
} else {
return _.startCase(this.name);
}
}
}
});
The template becomes this:
<div class='form-group form-group-sm'>
<label :for="name">{{labelText}}</label>
<input :id='name' :name='name' class='form-control' :value="value" #input="$emit('input', $event.target.value)"/>
</div>
</div>
And I use it like this:
<field :cols="8" name="name" v-model="product.name"></field>
The difference is that I'm not actually trying to pass a model prop down, I'm just passing a value, and listening for changes to that value. It seems to work pretty well and is clean and simple enough. My next challenge is passing an arbitary set of attributes to the input, but that's the subject of another question.
As the warning suggests you should not directly edit the prop you are passing for the value.
Instead use this as the original value and set a seperate value on the input from it - which you can pass to the v-model. If you need the parent to have the current value then also pass a prop that will allow you to update the param on the parent, i.e.
input component
# script
props: [
'origValue',
'valueChange',
],
data: {
inputValue: '',
...
},
mounted () {
this.inputValue = this.origValue
},
watch: {
inputValue () {
this.valueChange(this.inputValue)
},
...
},
...
# template
<input type="text" v-model="inputValue">
parent
# script
data () {
return {
fieldValue: 'foo',
...
},
},
methods: {
updateField (value) {
this.fieldValue = value
},
...
},
...
# template
<field :value-change="updateField" :orig-value="fieldValue"></field>