I am trying to write small app that change style depend on key in v-for loop. I can't figure out how to change style.
I want to colorize one as blue, two as green, three as red.
<div id="app">
<table>
<template v-for="(v,k) in tableData">
<tr v-bind:class="background-color: {{k}}">
{{v}}
</tr>
</template>
</table>
</div>
code:
new Vue({
el: '#app',
data: {
tableData:
{
"one": "I am one",
"two": "I am two",
"three": "I am three",
}
}
})
Here is my code https://jsfiddle.net/pevLgf0b/
it's seems that I should use computed property, but I can't understand how to do it in right way.
demo: https://jsfiddle.net/jacobgoh101/y295qd04/
you can use method to get different color dynamically
<script src="https://unpkg.com/vue"></script>
<div id="app">
<table>
<template v-for="(v,k) in tableData">
<tr v-bind:style="style(k)">
<td>
{{v}}
</td>
</tr>
</template>
</table>
</div>
new Vue({
el: '#app',
data: {
tableData: {
"one": "I am one",
"two": "I am two",
"three": "I am three",
}
},
methods: {
style(k) {
switch (k) {
case 'one':
return {
backgroundColor: 'red'
}
case 'two':
return {
backgroundColor: 'green'
}
case 'three':
return {
backgroundColor: 'blue'
}
}
}
}
})
You can add one more data object for colors.
https://jsfiddle.net/pevLgf0b/
new Vue({
el: '#app',
data: {
tableData:
{
"one": "I am one",
"two": "I am two",
"three": "I am three",
},
colorData:{
"one" : "blue",
"two" : "green",
"three" : "red",
}
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<table>
<template v-for="(v,k) in tableData">
<tr v-bind:style="{ 'background-color': colorData[k] }">
<td>{{v}} </td>
</tr>
</template>
</table>
</div>
In my case this work perfectly,
I've bind class based on the key. I have created a function which will return appropriate class based on the value and the style is applied.
Try this:
<template>
<table>
<template v-for="(v,k) in tableData">
<tr v-bind:class="applyStyle(k)">
<td>{{v}}</td>
</tr>
</template>
</table>
</template>
<script>
export default {
data() {
return {
tableData: {
one: "I am one",
two: "I am two",
three: "I am three"
}
}
},
methods: {
applyStyle(value) {
if (value == "one") {
return "applyRed";
}
if (value == "two") {
return "applyGreen";
}
if (value == "three") {
return "applyBlue";
}
}
}
};
</script>
<style>
.applyRed {
background-color: red;
}
.applyGreen {
background-color: green;
}
.applyBlue {
background-color: blue;
}
</style>
Related
I have a list of users. Click on a specific user the user edit form is populated but the only way I can get a value in the input is by putting the return in the
<input v-model="this.cl.data.USER_RLTNP_SCTY_ACCS_GRP.User_Name" ref=User_Name>
if I do
<input v-model="User_Name "v-bind:value="this.cl.data.USER_RLTNP_SCTY_ACCS_GRP.User_Name">
Nothing appears in the input.
If I use the v-model="this.cl.data....." the value of the user_name is in the input I'm not sure how the value is passed to my updateUser() function because normally I would use username = this.User_Name
Using apollo and Graphgl for the querying
<template>
<div>
<v-text-field label="User Name" ref="User_Name" v-model="User_Name" v-bind:value="this.cl.data.USER_RLTNP_SCTY_ACCS_GRP[0].User_Name" id="" placeholder="User Name"></v-text-field>
<v-btn v-on:click="editUser()">Edit</v-btn>
</div>
</template>
<script>
import gql from graphql-tag import { SCTY_ACCS_GRP, SCTY_ACCS_GRP_USER }
from './gqlqueries'
export default {
data: () => ({
users: [],
cl: '',
user_form: false,
user_name: ''
}),
methods: {
editForm: async function(userid){
this.cl = await this.$apollo.query({query : SCTY_ACCS_GRP_USER, variables: {id : userid}})
this.user_form = true
console.log(this.cl)
alert(this.cl.data.USER_RLTNP_SCTY_ACCS_GRP[0].User_Name)
},
editUser(){
this.user_name = this.User_Name
alert(this.user_name)
}
},
mounted: async function() {
this.users = await this.$apollo.query({ query: SCTY_ACCS_GRP })
// console.log(this.users.data.USER_RLTNP_SCTY_ACCS_GRP)
} }
</script>
I would assume the <input v-bind:value="this.cl.data...."> Would populate once The editForm() function is triggered. So how do I get the value of the User_Name when the editUser button is clicked
You could try list rendering.
A little example :
https://jsfiddle.net/L4xu9r5g/7/
var mapp = new Vue({
el: "#app",
data: {
currentuserinfo : undefined,
users: [
{ name: "John Doe", id : 12},
{ name: "Black Jack", id : 932},
{ name: "White Jack", id: 342}
],
userinfo:
[
{ userid: 12, favcolor: 'green', age : 23},
{ userid: 932, favcolor: 'red', age : 11},
{ userid: 342, favcolor: 'blue', age : 12}
]
},
methods:
{
selectuser : function(id)
{
//your query here
this.currentuserinfo = this.userinfo.filter(u => u.userid ==id)[0];
}
}
})
td, th
{
padding: 5px;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tbody>
<tr>
<th>Name</th>
<th>Select User</th>
</tr>
<tr v-for="user in users" :key="user.id">
<td>{{user.name}}</td>
<td><button #click="selectuser(user.id)">Select User</button></td>
</tr>
</tbody>
</table>
<div v-if="currentuserinfo === undefined">
Please select a user
</div>
<div v-if="currentuserinfo != undefined">
<span>Favourite color : {{currentuserinfo.favcolor}}</span><br/>
<span>Age : {{currentuserinfo.age}}</span><br/>
</div>
</div>
Any idea how to resolve this problem:
in this example, the author uses vue 2.3.2 which works perfect,
new Vue({
el: '#app',
data: {
users: [{
"id": "Shad",
"name": "Shad"
},
{
"id": "Duane",
"name": "Duane"
},
{
"id": "Myah",
"name": "Myah"
},
{
"id": "Kamron",
"name": "Kamron"
},
{
"id": "Brendon",
"name": "Brendon"
}
],
selected: [],
allSelected: false,
userIds: []
},
methods: {
selectAll: function() {
this.userIds = [];
if (this.allSelected) {
for (user in this.users) {
this.userIds.push(this.users[user].id.toString());
}
}
},
select: function() {
this.allSelected = false;
}
}
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="app">
<h4>User</h4>
<div>
<table>
<tr>
<th>Name</th>
<th>Select All<input type="checkbox" #click="selectAll" v-model="allSelected"></th>
</tr>
<tr v-for="user in users">
<td>{{ user.name }}</td>
<td><input type="checkbox" v-model="userIds" #click="select" :value="user.id"></td>
</tr>
</table>
</div>
<span>Selected Ids: {{ userIds }}</span>
</div>
when I switch it to 2.5.16 ( <script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script> ) , the behavior is wierd:
When click the selectAll checkbox, only that checkbox checked, but when I toggle it to uncheck, all the checkboses below get checked
For consistent browser functionality, I can recommended to not use click/change on checkboxes. Instead, bind the checkbox to a value (which you've already done), and then use a watcher on the value. This way, the real value of the checkbox will always accurately represent it's state. So you'd have something like this:
<input type="checkbox" v-model="allSelected">
Vue.component({..., {
data: function() {
return {
allSelected: false,
}
}
},
watch: {
allSelected: function(val){
//Use your source of truth to trigger events!
this.doThingWithRealValue(val);
}
}
});
You're already using your component data value of allSelected as the source of truth, so you should use this source of truth as the real triggering element value, not a click. Whenever the value of allSelected changes, your code will get ran. This solves the problem without the rendering order weirdness.
As pointed out by rob in the comments and in his answer you cannot rely on #click / #input / #change to have the same behaviour in all browsers in regards to their execution order relative to the actual model change.
There is an issue at the VueJS repository with a bit more context: https://github.com/vuejs/vue/issues/6709
The better solution is to watch the model for changes and then react accordingly.
new Vue({
el: '#app',
data: {
users: [{
"id": "Shad",
"name": "Shad"
},
{
"id": "Duane",
"name": "Duane"
},
{
"id": "Myah",
"name": "Myah"
},
{
"id": "Kamron",
"name": "Kamron"
},
{
"id": "Brendon",
"name": "Brendon"
}
],
selected: [],
allSelected: false,
userIds: []
},
methods: {
selectAll: function() {
this.userIds = [];
if (this.allSelected) {
for (user in this.users) {
this.userIds.push(this.users[user].id.toString());
}
}
},
select: function() {
this.allSelected = false;
}
},
watch: {
allSelected: function () {
this.selectAll()
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h4>User</h4>
<div>
<table>
<tr>
<th>Name</th>
<th>Select All<input type="checkbox" v-model="allSelected"></th>
</tr>
<tr v-for="user in users">
<td>{{ user.name }}</td>
<td><input type="checkbox" v-model="userIds" #click="select" :value="user.id"></td>
</tr>
</table>
</div>
<span>Selected Ids: {{ userIds }}</span>
</div>
I'm developing an exams portal application.
and this is my code.
<div class="" v-for="areas in knowledgeAreas">
{{areas.area}}<div class="progress" style="margin-top:10px;">
<div class="progress-bar" style="width:50%">{{areas.correctlyMarkedAnswers}} out of {{areas.numberOfQuestion}}</div>
</div>
</div>
and
data(){
return{
knowledgeAreas :[
{ area: 'Math',numberOfQuestion:10,correctlyMarkedAnswers:3,correctAnswersPercentage:12 },
{ area: 'IQ',numberOfQuestion:10,correctlyMarkedAnswers:5,correctAnswersPercentage:5 },
{ area: 'GK',numberOfQuestion:10,correctlyMarkedAnswers:8,correctAnswersPercentage:3 }
]
}
}
What I want is to dynamically pass the correctAnswersPercentage property's value to the CSS width property.
I created getProgress method then pass the value of correctAnswersPercentage during iteration.
Please check the snippet below:
new Vue({
el: "#app",
data: {
knowledgeAreas :[
{ area: 'Math',numberOfQuestion:10,correctlyMarkedAnswers:3,correctAnswersPercentage:50 },
{ area: 'IQ',numberOfQuestion:10,correctlyMarkedAnswers:5,correctAnswersPercentage:60 },
{ area: 'GK',numberOfQuestion:10,correctlyMarkedAnswers:8,correctAnswersPercentage:70 }
]
},
methods: {
getProgress: function(width) {
return {
'width': width + '%',
'background-color': 'yellow'
};
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<div id="app">
<div class="" v-for="areas in knowledgeAreas">
{{areas.area}}<div class="progress" style="margin-top:10px;">
<div class="progress-bar" v-bind:style="getProgress(areas.correctAnswersPercentage)">{{areas.correctlyMarkedAnswers}} out of {{areas.numberOfQuestion}}</div>
</div>
</div>
</div>
I'm studying VueJs and as programming allows multiple ways to get to the same result (some more or less elegant)...I'm pondering on what is the best way to filter lists.
Here are a few ways i've noticed lists could be filtered:
I will refer to this new Vue instance:
new Vue({
el: '#app',
data() {
return {
selected:['diesel','petrol'],
cars: [
{
"color": "blue",
"type": "diesel",
},
{
"color": "red",
"type": "petrol",
},
{
"color": "blue",
"type": "diesel",
},
]
}
}
Method #1: the "v-show".
Where any car type pushed into the "selected" array will be rendered.
<div id="app>
<span v-for="(car, key) in cars"
v-show="selected.includes(car.type)"
>
{{car.color}} <br>
{{joke.type}} <br>
</span>
</div>
Method #2: Using a computered Property and a filter
<div id="app>
<span v-for="(car, key) in filteredCars">
{{car.color}} <br>
{{joke.type}} <br>
</span>
</div>
computed: {
filteredCars: function(){
var selected = this.selected
return this.cars.filter(function(car){
if (selected.indexOf(car.type) >= 0) {
return joke.type
}
}
)}
}
Any thoughts and best practices??
Thanks again.
I want to make pagination for my table but, when I run, my data does not appear anything. I am confused my code which is wrong perhaps here anyone can help me.
var newVue = new Vue({
el: '#app',
data: {
items: [
{ name: "item #1" }, { name: "item #2" }, { name: "item #3" }, { name: "item #4" },
{ name: "item #5" }, { name: "item #6" }, { name: "item #7" }, { name: "item #8" },
{ name: "item #9" }, { name: "item #10" }, { name: "item #11" }, { name: "item #12" }
],
start: 0,
limit: 2,
pagination: null,
total: 12
},
computed: {
filtered: function(){
return this.items.slice(0, this.limit)
}
},
mounted: function() {
this.limit = parseInt(this.pagination);
},
watch: {
pagination: function() {
this.limit = parseInt(this.pagination);
if(this.limit != this.start && this.start > 0)
this.start = parseInt(this.pagination);
this.limit = this.start + parseInt(this.pagination);
}
},
methods: {
paginate: function(direction) {
if(direction === 'next') {
this.start += parseInt(this.pagination);
this.limit += parseInt(this.pagination);
}
else if(direction === 'back') {
this.limit -= parseInt(this.pagination);
this.start -= parseInt(this.pagination);
}
},
},
filters: {
paginate: function(array, start, limit) {
return array.slice(start, limit);
}
}
});
.pager button {
background: #fff;
border: 1px solid #ddd;
border-radius: 15px;
color: #337AB7;
padding: 7px 13px;
text-align: center;
}
.pager button:hover {
background: #eee;
cursor: pointer;
outline: none;
}
.pager button:disabled {
background: #eee;
color: #bbb;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.min.css" rel="stylesheet"/>
<div id="app">
<table class="table table-striped table-advance table-table-hover table-bordered">
<thead>
<th>Item</th>
</thead>
<tbody>
<tr v-for="item in filtered | paginate">
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-md-12 center">
<ul class="pager">
<li>
<button #click="paginate('previous')" :disabled="start <= 0">
Previous
</button>
</li>
<li>
<button #click="paginate('next')" :disabled="limit >= total">
Next
</button>
</li>
</ul>
</div>
</div>
</div>
<script src="https://unpkg.com/vue#2.1.10/dist/vue.js"></script>
There are few problems with your code, after removing those your code works as can be seen here in fiiddle.
You dont need | paginate with v-for as filtered is computed property which will give you paginated result
<tbody>
<tr v-for="item in filtered | paginate">
<td>{{ item.name }}</td>
</tr>
</tbody>
in filtered you needed to pass correct params in slice method.
computed: {
filtered: function(){
return this.items.slice(this.start, this.limit)
}
},`