When radio selected, change image src on vue.js version2 - javascript

I want to change image and that trigger an image update.
This is for example
http://jsbin.com/kuluyike/3/edit?html,js,output
<div id="colorPicker">
<img v-attr="src:color" alt="{{color}}">
<ul>
<li v-repeat="colors">
<label>
<input type="radio" id="{{name}}" name="color" v-model="color" value="{{image}}">
{{name}}
</label>
</li>
</ul>
</div>
var cp = new Vue({
el: '#colorPicker',
data: {
colors: [
{
name: 'red',
image: 'red.jpg'
},
{
name: 'pink',
image: 'pink.jpg'
},
{
name: 'blue',
image: 'blue.jpg'
}
]
}
});
But this is not working on Vue.js version 2.x
How do I change the code so working based on version 2.x

In Vue 2.0, the syntax has changed for attributes, this means, you now have to declare your attributed as the following:
<img :src="color" :alt="color">
<input type="radio" :id="name" :name="color" v-model="color" :value="image">
In Vue 2.0, the syntax for loops has changed from v-repeat to v-for::
<li v-for="(colorInfo, index) in colors">
<input type="radio" :id="colorInfo.name" name="color" v-model="color" :value="colorInfo.image">
In Vue 2.0 development mode, a warning is emitted when you access an undeclared property
data: {
// ...
color: undefined,
},
var cp = new Vue({
el: '#colorPicker',
data: {
color: undefined,
colors: [
{
name: 'red',
image: 'red.jpg'
},
{
name: 'pink',
image: 'pink.jpg'
},
{
name: 'blue',
image: 'blue.jpg'
}
]
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="colorPicker">
<img :src="color" :alt="color">
<ul>
<li v-for="(colorInfo, index) in colors">
<label>
<input type="radio" :id="colorInfo.name" name="color" v-model="color" :value="colorInfo.image">
{{colorInfo.name}}
</label>
</li>
</ul>
</div>
See also: Migration from Vue 1.x - Vuejs

You can use v-for here for looping in Vue 2.x like:
new Vue({
el: '#colorPicker',
data: {
color: null,
colors: [{
name: 'red',
image: 'red.jpg'
},
{
name: 'pink',
image: 'pink.jpg'
},
{
name: 'blue',
image: 'blue.jpg'
}
]
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="colorPicker">
<img :src="color" :alt="color" v-if="color" />
<ul>
<li v-for="c in colors">
<label>
<input type="radio" name="color" v-model="color" :value="c.image"/>
{{c.name}}
</label>
</li>
</ul>
<p v-if="color"><b>Selected image name: </b> {{color}}</p>
</div>

Related

How to dynamically set an Image object src in javascript and Vue

I'm trying to teach myself javascript and Vue.js. I was following the documentation on Vue's site and modifying their demonstrations as an exercise. I wanted to change their looping directive example to dynamically add images to the list from a specified url. I can't seem to get the image to show despite setting the image properties src field. I have verified that everything runs and the field is in fact getting set. I assume I must be misunderstanding something related to the DOM or ordering of events.
Thanks in advance.
HTML
<script src="https://unpkg.com/vue#next"></script>
<div id="list-rendering" class="demo">
<input v-model="imgsrc"></input>
<button v-on:click="setImage"> Set</button>
<ol>
<li v-for="todo in todos">
{{ todo.text }} {{todo.image}}
</li>
</ol>
</div>
CSS
.demo {
font-family: sans-serif;
border: 1px solid #eee;
border-radius: 2px;
padding: 20px 30px;
margin-top: 1em;
margin-bottom: 40px;
user-select: none;
overflow-x: auto;
}
Javascript
const ListRenderingApp = {
data() {
return {
todos: [
{ text: 'Learn JavaScript',
image: new Image(16,16)},
{ text: 'Learn Vue',
image: new Image(16, 16)},
{ text: 'Build something awesome',
image: new Image(16, 16)}
],
imgsrc: ""
}
},
methods:{
setImage(){
this.todos.map(todo => todo.image.src = this.imgsrc)
}
}
}
Vue.createApp(ListRenderingApp).mount('#list-rendering')
When using v-for make sure to add :key. Docs
Also pay attention to your html elements. <img> & <input>.
Also return the result of .map() to this.todos. Docs
new Vue({
el: "#app",
data: {
imgSrc: 'https://via.placeholder.com/150/FF0000',
todos: [
{ text: "Learn JavaScript", image: 'https://via.placeholder.com/150/0000FF' },
{ text: "Learn Vue", image: 'https://via.placeholder.com/150/0000FF' },
{ text: "Play around in JSFiddle", image: 'https://via.placeholder.com/150/0000FF' },
{ text: "Build something awesome", image: 'https://via.placeholder.com/150/0000FF' }
]
},
methods: {
setImage: function(todo){
this.todos = this.todos.map(todo => ({ ...todo, image: this.imgSrc }))
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<small>image url</small>
<input v-model="imgSrc" />
</div>
<br />
<div>
<button #click="setImage()">
Click to set Image
</button>
</div>
<ol>
<li v-for="(todo, i) in todos" :key="i">
<label>
{{ todo.text }}
</label>
<img :src="todo.image" alt="img" width="100" height="100">
</li>
</ol>
</div>
try running this snippet & click the "Click to set Image"
try this.
<div id="list-rendering" class="demo">
<input v-model="imgsrc"></input>
<button v-on:click="setImage"> Set</button>
<ol>
<li v-for="(todo, index) in todos :key="index"">
{{ todo.text }}
<img :src="todo.image"/>
</li>
</ol>
</div>

How to change the specific checkbox label class #change in Vue?

Background: I have a list of checkboxes that is bound to a names array. I am trying to change the class of the specific name once the checkbox is clicked.
Problem: Once a checkbox is clicked it changes the class of all the names instead of the specific name attached to the checkbox.
JSFiddle of the issue:
JSFiddle
HTML
<div id="app">
<ul>
<li v-for="name in names" :key="index">
<input #click="available = !available" type="checkbox">
<label :class="{available:available}" >{{name.name}}</label>
</li>
</ul>
</div>
Vue instance
var app = new Vue({
el: '#app',
data: {
available: false,
names: [{'name':'Jerry'},{'name':'Eddie'},{'name':'Kerry'},{'name':'Jane'}]
}
})
Css
.available{
text-decoration: line-through;
}
Ad the available variable to each name object and use a method to update the available property:
var app = new Vue({
el: '#app',
data: {
names: [
{'name':'Jerry', 'available': false},
{'name':'Eddie', 'available': false},
{'name':'Kerry', 'available': false},
{'name':'Jane', 'available': false}
]
},
methods: {
updateAvailable(index) {
// Update the available property on the specific object with its index
this.names[index].available = !this.names[index].available
}
}
})
Then in your template, call the method updateAvailable:
<div id="app">
<ul>
<li v-for="(name, index) in names" :key="index">
<input #click="updateAvailable(index)" type="checkbox">
<label :class="{available: name.available}" >{{name.name}}</label>
</li>
</ul>
</div>
Move the available property in to each name element and toggle name.available in your template. You can even use v-model on your checkboxes.
const names = [{'name':'Jerry'},{'name':'Eddie'},{'name':'Kerry'},{'name':'Jane'}]
const app = new Vue({
el: '#app',
data: () => ({
names: names.map(name => ({ ...name, available: false }))
})
})
.available {
text-decoration: line-through;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app">
<ul>
<li v-for="(name, i) in names">
<input :id="`name_${i}`" v-model="name.available" type="checkbox">
<label :for="`name_${i}`" :class="{ available: name.available }">
{{name.name}}
</label>
</li>
</ul>
</div>

Show image based on chosen radio input

As the title says, how to make this in VueJS
There is a start point https://jsbin.com/tomevukisa/edit?html,js,output
I guess it's something about index matching because I did something similar with jQuery in this way
$('.Colors > li').on('mouseenter', function() {
var i = $(this).index();
$('.Items > li.active').fadeOut(200, function() {
$(this).removeClass('active').parent('ul').children('li').eq(i).fadeIn(100).addClass('active');
});
});
But now it's about VueJS only.
Thanks.
You need to specify a value for the radio buttons. Since you want to compare based on $index, that's the value to set.
<input type="radio" name="color" value="{{$index}}" v-model="picker">
To control whether something displays, use the v-show binding:
v-show="+$index === +picker"
I use unary + to ensure that both are numeric.
new Vue({
el: 'body',
data: {
picker: 1,
images: [
{img_src: 'http://cl.jroo.me/z3/q/R/R/d/a.aaa-Unique-Nature-Beautiful-smal.jpg'},
{img_src: 'http://www.nature.com/nature/journal/v477/n7365/images/477415a-f1.2.jpg'},
{img_src: 'http://scr.templatemonster.com/35100/35151_gall_nature_small_3.jpg'}
],
colors: [
{id: 1, name: 'Black'},
{id: 2, name: 'Red'},
{id: 3, name: 'Green'}
]
}
});
ul {
list-style: none;
}
ul li img {
width: 110px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.16/vue.js"></script>
<ul class="Items">
<li v-for="image in images">
<img v-show="+$index === +picker" :src="image.img_src" >
</li>
</ul>
<ul class="Colors">
<li v-for="color in colors">
<input type="radio" name="color" value="{{$index}}" v-model="picker">
<span>{{ color.name }}</span>
</li>
</ul>

Knockout.js {{each}} not listing items in javascript template

I've created a simple app that should iist each item from a model in a list, created using a javascrit template.
Fiddle
Html:
<div id="tagsList" class="box">
<div class="box-head">
<h2 class="left">Tags</h2>
</div>
<div class="box-content">
<input type="text" placeholder="Add New Tag" />
<button>+ Add</button>
<div data-bind="template: 'tagsTempl'"></div>
</div>
</div>
<script id="tagsTempl" type="text/html">
<ul>
{{each tags}}
<li class="tagItem">
<span>${Name}</span>
<div>
Edit
Delete
</div>
</li>
{{/each}}
</ul>
</script>
Javascript:
$(function () {
//$("#tagDialog").hide();
var data = [
{ Id: 1, Name: "Ball Handling" },
{ Id: 2, Name: "Passing" },
{ Id: 3, Name: "Shooting" },
{ Id: 4, Name: "Rebounding" },
{ Id: 5, Name: "Transition" },
{ Id: 6, Name: "Defense" },
{ Id: 7, Name: "Team Offense" },
{ Id: 8, Name: "Team Defense" }
];
var viewModel = {
tags: ko.observableArray(data),
tagToAdd: ko.observable(""),
addTag: function() {
this.tags.push({ Name: this.tagToAdd() });
}
}
ko.applyBindings(viewModel)
});
Output of list:
{{each tags}}
${Name}
Edit Delete
{{/each}}
The scripts file is accessible through viewing source. I'm not sure where my error is. Any help?
I updated your fiddle. Now it is working like you want it to: The list of tags is being rendered using the knockout standard method as described in the docs.
HTML
<ul data-bind="template: {name: 'tagsTempl', foreach: tags}"></ul>
Template
<script id="tagsTempl" type="text/html">
<li class="tagItem">
<span data-bind="text: Name"></span>
<div>
Edit
Delete
</div>
</li>
</script>
Also I connected the viewmodel to the view.
For example:
<button data-bind="click: addTag">+ Add</button>
You simply forgot most of it. I suggest you follow the interactive tutorials on how to do this.

Vue.js v-model data object

So I just started playing around with Vue.js. But I am having some problems with simple tasks like adding new "news item" to the array. JSFiddle included so if someone can tell me what I am doing wrong..
http://jsfiddle.net/pL5taqp6/
HTML
<div id="app">
<input type="text" v-model="news.title">
<input type="text" v-model="news.url">
<ul>
<li v-for="n in news">
{{ n.title }} - {{ n.url }}
</li>
</ul>
</div>
JS
new Vue({
el: '#app',
data: {
news: [
{ title: 'Test Title', url: '/test-title'}
]
}
});
You need a separate method to add items to news array. I added super simple variant of such function.
http://jsfiddle.net/00953sor/
HTML:
<div id="app">
<form #submit="addItem">
<input type="text" v-model="itemTitle">
<input type="text" v-model="itemUrl">
<button type="submit">Add</button>
</form>
<ul>
<li v-for="n in news">
{{ n.title }} - {{ n.url }}
</li>
</ul>
<pre>{{ $data | json }}</pre>
</div>
JavaScript:
new Vue({
el: '#app',
data: {
news: [{
title: 'Test Title',
url: '/test-title'
}]
},
methods: {
addItem: function(e) {
e.preventDefault(); // prevent page refresh
this.news.push({
"title": this.itemTitle,
"url": this.itemUrl
});
this.itemTitle = this.itemUrl = '';
}
}
});

Categories