How to use Vue.js variable/parameter inside v-if condition - javascript

I need to pass a dynamic variable into v-if attribute.
I tried multiple ways but it doesn't produce the expected result.
So far, I have this: v-if="customDropdown === {{row.name}}"
How can I conditionally and dynamically render the element, please?
Thank you in advance.

You cannot use interpolation in Vue directives/attributes.
To bind to v-if or v-for use variables directly:
<div v-if="value.someProperty"></div>
To bind to other attributes/properties use v-bind: or shorthand : as follows:
<div :directive="value"></div>
Template Syntax documentation

You need binding the row.name to data object in vue:
export default {
data() {
return {
customDropdown: 'something',
row: {name: 'something'},
}
}
}
and then use it in the v-if statement:
<div v-if="customDropdown == row.name">You see me if customDropdown is equal to row.name</div>

First, you cannot interpolate directives/attributes and second, it's not clear, but I think you want to check the condition while iterating by a array.
You can use the template structure below:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div
v-for="row in arrayList"
v-if="customDropdown === row.name"
>
Show row content: {{ row }}
</div>
</div>
With the data structure below to achieve you goal:
new Vue({
el: '#app',
data: {
customDropdown: 'first',
arrayList: [
{
name: 'first',
},
{
name: 'second',
},
],
},
})

Just use the properties name,
For example
export default {
data() {
return {
var: true
}
}
}
html
<span v-if="var">I only appear when the condition is true</span>

Related

Can we add more than one value in VueJs "type" attribute?

I know this is such a ridiculous question, but could we add more than one value in 'type' property? Such as type="green rounded" or type="danger priority"
You can make a prop with a string type in your component, then use a method to check if the word is included in the string.
For example, prop:
props: {
type: {
type: String
}
}
Create a function to check if the word is included:
propIncludes(segment) {
return this.type.includes(segment);
}
Use the method wherever you want to check:
<p v-if="propIncludes('first')">First prop</p>
<p v-if="propIncludes('second')">Second prop</p>
And to add your new type to your component, simply go to the parent:
<Test type="first second"/>
I've added the sandbox below:
https://codesandbox.io/s/heuristic-shamir-o0yk9
You can have one value for each property. For example type="green rounded" is still one value, it's up to you how you want to parse that value.
I created a quick demo that has type as a prop and splits it by a space.
Vue.component("MyModal", {
template: "<div>{{type ? type.split(' ').join(', ') : 'No Type'}}</div>",
props: ["type"]
});
new Vue({
el: "#app"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<My-Modal type="danger red"></My-Modal>
</div>

How to reference a child component from the parent in Vue

I'm trying to figure out the Vue-way of referencing children from the parent handler.
Parent
<div>
<MyDropDown ref="dd0" #dd-global-click="ddClicked"></MyDropDown>
<MyDropDown ref="dd1" #dd-global-click="ddClicked"></MyDropDown>
<MyDropDown ref="dd2" #dd-global-click="ddClicked"></MyDropDown>
</div>
export default {
methods: {
ddClicked: function(id) {
console.log("I need to have MyDropDown id here")
}
}
}
Child
<template>
<h1>dropdown</h1>
<Button #click="bclick"></Button>
</template>
export default {
methods: {
bclick: function() {
this.$emit('dd-global-click')
}
}
}
In the parent component I need to see which dropdown was clicked.
What I've tried so far
I tried to set "ref" attribute in the parent. But I can't refer to this prop within the child component. Is there a way to do it? There is nothing like this.ref or this.$ref property.
I tried to use $event.targetElement in the parent, but it looks like I'm mixing Real DOM and Vue Components together. $event.targetElement is a DOM like . So in the parent I have to go over the tree until I find my dropdown. It is ugly I guess.
I set an additional :id property for the dropdown making it the copy of the 'ref' property. In the blick and I called this.$emit('dd-global-click', this.id). Later in the parent I check this.$refs[id]. I kind of works, but I'm not really content with it, because I have to mirror attributes.
Using the _uid property didn't work out either. On top of that, I think, that since it starts with an underscore it is not a recommended way to go.
It seems like a very basic task, so there must be a simplier way to achieve this.
If this custom dropdown element is the top level one (the root element) in the component, you could access the native DOM attributes (like id, class, etc) via this.$el, once it's mounted.
Vue.component('MyDropdown', {
template: '#my-dropdown',
props: {
items: Array
},
methods: {
changed() {
this.$emit('dd-global-click', this.$el.id);
}
}
})
new Vue({
el: '#app',
data: () => ({
items: [
{
id: 'dropdown-1',
options: ['abc', 'def', 'ghi']
},
{
id: 'dropdown-2',
options: ['jkl', 'lmn', 'opq']
},
{
id: 'dropdown-3',
options: ['rst', 'uvw', 'xyz']
}
]
}),
methods: {
ddClicked(id) {
console.log(`Clicked ID: ${id}`);
}
}
})
Vue.config.devtools = false;
Vue.config.productionTip = false;
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.11"></script>
<div id="app">
<my-dropdown
v-for="item of items" :key="item.id"
:id="item.id"
:items="item.options"
#dd-global-click="ddClicked">
</my-dropdown>
</div>
<script id="my-dropdown" type="text/x-template">
<select #input="changed">
<option v-for="item of items" :key="item" :value="item">
{{item}}
</option>
</select>
</script>

How to set default value on dynamic input fields in Vue.js?

I have created a dynamic input fields but the problem is that I don't know how to set default values on that dynamic fields for example number "1". Can anyone help me with that? Thanks
Here is my example
new Vue({
el: '#app',
data: {
result: [],
array: [{
id: 1
}, {
id: 2
}, {
id: 3
}]
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="(item, index) in array" :key="item.id">
<input type="number" :id="item.id" v-model="result[index]">
<br>
</div>
<span>Result: {{ result }}</span>
</div>
As Vue js is reactive you can simply set initial value in result
new Vue({
el: '#app',
data: {
result: ["1","1","1"],
array: [{
id: 1
}, {
id: 2
}, {
id: 3
}]
}
})
According to the official documentation,
v-model will ignore the initial value, checked or selected attributes
found on any form elements. It will always treat the Vue instance data
as the source of truth. You should declare the initial value on the
JavaScript side, inside the data option of your component.
I think it is a design decision of Vue to use the benefit of Vue instance’s reactive system rather than listening to DOM updates when such attributes are updated.
So you can put directly your default values into the result array, here's the updated working jsfiddle.

Passing the properties of an object as props Vuejs

hi everyone,
I have some confusion. I have two component ( child and parent component) and I pass the properties of an object as props
<child :child-data="abc" ></child>
Vue.component('childComponent', {
props: ['childData'],
data: function(){
return {
count:this.childData,// recommend use Vue.util.extend
}
},
});
Vue will recursively convert "data" properties of childComponent into getter/setters to make it “reactive”.
So why doesn't it automatic bind data to the template? I read some recommend use Vue.util.extend. Why Vue.util.extend?
UPDATE
my example:
https://jsfiddle.net/hoanghung1995/xncs5qpd/56/
when i set default value of parentData ,childDataA will display it. But when i use v-model to override parentData then childDataA not “reactive”. I must use "watch" to override "data" ,similar to childDataB
Vue.util.extend example: https://jsfiddle.net/sm4kx7p9/3/
Why do Vue.util.extend work fine but not use "watch"?,
To explain what is actually happening in the background, Linus Borg has as excellent answer for your question. To summarize his answer, the reason why your approach doesn't work is being data is a computed property while props are being passed in as primitive types. In other words, data makes a copy of your props (instead of passing by reference).
Another way to bypass this is to declare your childData as computed properties instead of data, i.e.:
computed: {
childDataA() {
return this.childPropsA;
},
childDataB() {
return this.childPropsB;
}
}
The reason why using computed works is because the computed properties now watches changes to their dependencies.
A proof-of-concept example based on your original fiddle:
Vue.component('child', {
props: ['childPropsA', 'childPropsB'],
template: "#sub",
computed: {
childDataA() {
return this.childPropsA;
},
childDataB() {
return this.childPropsB;
}
}
});
new Vue({
el: '#app',
data: {
parentData: '123'
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
parentData:{{parentData}}<br>
<input type="text" v-model="parentData">
<child :child-props-a="parentData" :child-props-b="parentData"></child>
</div>
<template id="sub">
<div>
<p> 1- {{ childDataA }}</p>
<p> 2- {{ childDataB }}</p>
</div>
</template>
The approach above is functionally identical to the data + watch approach, but I find it rather cumbersome and adds unnecessary verbosity to your code:
data: function() {
return {
childDataA: this.childPropsA,
childDataB: this.childPropsB
};
},
watch: {
childPropsA() {
this.childDataA = this.childPropsA;
},
childPropsB() {
this.childDataB = this.childPropsB;
}
}
Vue.component('child', {
props: ['childPropsA', 'childPropsB'],
template: "#sub",
data: function() {
return {
childDataA: this.childPropsA,
childDataB: this.childPropsB
};
},
watch: {
childPropsA() {
this.childDataA = this.childPropsA;
},
childPropsB() {
this.childDataB = this.childPropsB;
}
}
});
new Vue({
el: '#app',
data: {
parentData: '123'
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
parentData:{{parentData}}<br>
<input type="text" v-model="parentData">
<child :child-props-a="parentData" :child-props-b="parentData"></child>
</div>
<template id="sub">
<div>
<p> 1- {{ childDataA }}</p>
<p> 2- {{ childDataB }}</p>
</div>
</template>
Watch does only watch properties which are indeed reactive. Passing objects doesn`t makes their properties reactive. Just pass the properties that you want as props.
With Vue.util.extend you force the property to be reactive in this instance.

How can i pass a property to a directive on vue js?

how can i get the property value on a v-show or v-if directive? i've already try to pass like the example bellow but not succeed.
v-show="cabin >= {{ number }}" number="5"
i'm stuck with this and since vue.js it's kind of new its so hard to find documentation and examples.
If you're using Vue Components, then you could do something like this:
Vue.Component('my-comp', {
template: '#my-template',
props: [
'number',
],
data: function(){
return{
cabin: 4
};
}
}):
and then in your view, use it like this:
<my-comp v-show="cabin >= number" number="5"></my-comp>
<template id="my-template">
<div>Lorem Ipsum</div>
</template>
Once you used a custom attribute (number), I guess that you used a component.
So, as he said #user3324298, you need something like this:
Vue.Component('my-comp', {
template: '#my-template',
props: ['number'],
data: function() {
return {
cabin: 4
}
}
})
But the template, should be something like this:
<template id="my-template">
<div v-show="cabin >= number" number="5">
<div>Lorem Ipsum</div>
</div>
</template>
<my-comp></my-comp>
v-show should be into the scope of component.

Categories

Resources