I am working on a site where the user can select an image via radio selection.
I would like to dynamically update the image URL depending on selection of the user. My approach is to use a computed variable which returns the URL from a list of objects depending on the selection of the user.
<template>
<v-img
:src="require(currBackgroundURL)"
class="my-3"
contain
width="397"
height="560"
></v-img>
</template>
<script>
// data() ...
currBackground: 0,
backgrounds: [
{
name: "Flowers",
url: "../assets/background/bg_1.png"
},
// ...
computed: {
currBackgroundURL: function() {
return this.backgrounds[this.currBackground].url
}
}
</script>
Unfortunately, i get an error which says Critical dependency: the request of a dependency is an expression.
And the browser console says: [Vue warn]: Error in render: "Error: Cannot find module '../assets/background/bg_1.png'"
Question: What is the right way to switch the URL of the image dynamically?
Thanks for your help!
Here is a working example:
var app = new Vue({
el: '#app',
data: () => ({
currBackground: 0,
backgrounds: [
{
name: "black",
url: "https://dummyimage.com/600x400/000/fff"
},
{
name: "blue",
url: "https://dummyimage.com/600x400/00f/fff"
},
{
name: "red",
url: "https://dummyimage.com/600x400/f00/fff"
}
]
}),
computed: {
currBackgroundURL: function() {
return this.backgrounds[this.currBackground].url
}
},
methods: {
nextImage() {
this.currBackground += 1
if (this.currBackground > 2) {
this.currBackground = 0
}
}
}
})
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.18/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<div id="app">
<v-btn #click="nextImage()">Change image</v-btn>
<v-img
:src="currBackgroundURL"
class="my-3"
contain
width="397"
height="560"
></v-img>
</div>
</body>
I removed the require.
The src is a link/path so you don't need require. require will try to take a path and load it into a module instead of a link/path.
Hopefully, this helps.
Related
I'm pretty new in Vue and I'm trying to write down a function that returns true or false on a given data when input modified. I have 4 different data that I need possibly to change the truthiness.
My logic was to produce a function that accepts data as parameter but... It doesn't work. Maybe it's not the proper way to go for...
Here the HTML:
<input type="text" v-model="bannerContent.button" #input="checkMaxChar(48,bannerContent.button.length,isButtonTooLong)" id="banner-button">
And the JS
var app = new Vue({
el: '#app',
data: {
bannerContent: {
title : 'Title',
text: 'Text',
copyright: 'Copyright',
button: 'Button'
},
isButtonTooLong: false,
},
methods: {
checkMaxChar: function(a,b,c) {
var vm = this
if( a < b ) {
vm.c = true;
};
console.log(this.c);
}
}
})
I'm not sure why you are doing var vm = this and also where do you defined c?
for your purpose define c in the data section like code below and work wit your input:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<input
type="text"
v-model="bannerContent.button"
#input="checkMaxChar(48,bannerContent.button.length,isButtonTooLong)"
id="banner-button"
/>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
bannerContent: {
title: "Title",
text: "Text",
copyright: "Copyright",
button: "Button",
},
isButtonTooLong: false,
c: false,
},
methods: {
checkMaxChar(a, b, c) {
if (a < b) {
this.c = true;
}
console.log(this.c);
},
},
});
</script>
</html>
Hope it helps You ;)
Vue - #input is triggered by :placeholder in Internet Explorer 11 immediately upon page load not when entering a value. That is, the problem is only in the explorer. When the page loads, input is triggered immediately, but only if there is a placeholder
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Тег SCRIPT</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<component-c/>
</div>
<script type="text/javascript">
var ComponentA = Vue.component('ComponentA', {
props: ['field'],
methods: {
//#input is triggered by :placeholder in Interner Exployer 11 immediately upon page load not when entering a value
validator: function (ev){
console.log(ev.target.value, 'value in validator');
}
},
computed: {
fieldPlaceholder: function () {
return this.field.placeholder;
},
},
template: '<input type="password" #input="validator" :placeholder = "fieldPlaceholder">'
});
var ComponentС = Vue.component('ComponentB', {
data: function () {
return {
field: {
placeholder: 'place'
}
}
},
components: {
'component-a': ComponentA,
},
template: '<component-a :field = "this.field" />'
})
var app = new Vue({
el: '#app',
components: {
'component-c': ComponentС,
}
})
</script>
</body>
</html>
im learnign VUE JS and I dont understand this behavior (strange for me).
I want to get list of people in table via Vue component.
Html tag table is under the list.
Documentation says: Every compoment must have one single root, ok I can wrap each tr with tbody but it doesnt solve this problem.
How to solve it?
<html>
<head>
<link rel="stylesheet" href="index.css">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table>
<row
v-for="people in peoples"
v-bind:people="people"
v-bind:key="people.id">
</row>
</table>
</div>
<script>
Vue.component('c-tr', {
template: '<tr></tr>'
});
Vue.component('row', {
props: ['people'],
template: '<tr><td>{{ people.name }}</td></tr>'
});
var app = new Vue({
el: '#app',
data: {
peoples: [
{ id: 20, name: 'Roman' },
{ id: 30, name: 'Vasek' },
{ id: 40, name: 'Ondra' }
]
}
})
</script>
</body>
</html>
I am trying to implement a Vue Component with a custom render function.
As soon as my template has nested HTML elements, i get this error:
TypeError: this.$options.staticRenderFns is undefined
How do I implement staticRenderFns?
Code:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<comp temp="temp1"></comp>
</div>
<script>
var myTemplates = new Array();
myTemplates['temp1'] = Vue.compile("<div><div>This template will come from an AJAX source</div></div>").render;
var Comp = {
props: ["temp"],
data() {
return {
renderFunc: myTemplates[ this.$props.temp ],
}
},
render(h) {
return this.renderFunc()
}
};
new Vue({
el: "#app",
data: { },
components: { Comp }
});
</script>
</body>
</html>
I am trying to get to a point where I can have multiple component types being rendered within a single parent. It's not something which is easy to search for answers on.
I know that it is differentiating the components by adding something to the templates to distinguish them, but if I pass data as you'll see below, I get nothing, any tips?
Edit: I also don't want to have to render out these components in the HTML for this to work, needs to be passed in via JS.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="app">
<component v-for="widget in widgets" :is="widget.type"></component>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<script>
Vue.config.debug = true
Vue.component('component-a', {
template: '<p>{{foo}}</p>',
props: ['foo',]
});
Vue.component('component-b', {
template: '<p>{{bar}}</p>',
props: ['bar',]
});
new Vue({
el: "#app",
data: {
widgets: [
{
type: "component-a",
foo: 'Hello'
},
{
type: "component-b",
bar: "World",
},
]
}
});
</script>
</body>
</html>
The issue is that you're not passing any props for the foo and bar elements
<!doctype html>
<html>
<head>
<title></title>
</head>
<body>
<div id="app">
<component v-for="widget in widgets" :is="widget.type" :foo="widget.foo" :bar="widget.bar"></component>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<script>
Vue.config.debug = true
Vue.component('component-a', {
template: '<p>{{foo}}</p>',
props: ['foo',]
});
Vue.component('component-b', {
template: '<p>{{bar}}</p>',
props: ['bar',]
});
new Vue({
el: "#app",
data: {
widgets: [
{
type: "component-a",
foo: 'Hello'
},
{
type: "component-b",
bar: "World",
},
]
}
});
</script>
</body>
</html>
jsFiddle
In your example the components are rendering with empty strings so you're not seeing the values you're trying to pass. when using interchangeable components it's often best to use a common value interface. Something along the lines of:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="app">
<component v-for="widget in widgets" :is="widget.type" :value="widget.value"></component>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<script>
Vue.config.debug = true
Vue.component('component-a', {
template: '<p>{{value.foo}}</p>',
props: ['value',]
});
Vue.component('component-b', {
template: '<p>{{value.bar}}</p>',
props: ['value',]
});
new Vue({
el: "#app",
data: {
widgets: [
{
type: "component-a",
value: {
foo: 'Hello'
}
},
{
type: "component-b",
value: {
bar: "World",
}
},
]
}
});
</script>
</body>
</html>
So that the components only pass the single value object to the component necessary and the component pulls the unique values from that object.