Dynamic computed property in html - vuejs2

I'm using php for creating set of computed properties in my app based on ID property of each object in my main array of data stored in property deals. So i have now computed properties like list_10_deals_cnt, list_20_deals_cnt, list_30_deals_cnt etc. Now, how can I create these dynamic created properties in span with class dials__cnt while looping my array of data? {{'list_'+el.id+'_deals_cnt'}} is not working as i wish, its display just a string like list_10_deals_cnt instead to display a computed value.
P.S. sorry about my english.
<div class="dials" id="app">
<div class="dials__column" v-for="(el, index) in deals">
<div class="dials__header">
<div>{{el.title}}</div>
<div>сделок: <span class="dials__cnt">{{`'list_'+el.id+'_deals_cnt'`}}</span>, <span></span> руб</div>
</div>
<draggable drag-class="draggable-ghost__class" class="dials__block" :list="el.items" group="deal" #change="log(el.id, $event)">
<div
class="dials__card"
v-for="(el, index) in el.items"
:key="el.title"
>
<div class="card__header">
<div class="card__title">{{ el.customer_name }}, {{ el.customer_company_name }}</div>
<div class="card__date">{{ el.created_at }}</div>
</div>
<div class="card__body">
<a :href="'/deal/detail/'+el.id" class="card__link">{{ el.title }}</a>
</div>
<div class="card__footer">
<span class="card__price">{{ el.price }} руб </span>
<span v-for="(tag, index) in el.tags" class="card__tag">{{ tag }}</span>
</div>
</div>
</draggable>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
deals: <?php echo json_encode($deals, JSON_UNESCAPED_UNICODE); ?>
},
computed: {
<?php
foreach ($deals as $k=>$v) {
echo 'list_'.$v->id.'_deals_cnt: function() {return this.deals['.$k.'].items.length},';
}
?>
},
methods: {
log: function(id, evt) {
if (evt.hasOwnProperty('added')) {
let dealID = evt.added.element.id;
console.log('сделка ID '+dealID+' перемещена в статус '+id+'. Отправляем аякс запрос на обновление статуса в бд');
// ajax for update
}
}
}
});
</script>

Hi
Problem 1
you will not be able to get the value of computed property by using this
{{`'list_'+el.id+'_deals_cnt'`}}
for the same reason as console.log('vari' + 'able') doesn't print out value of variable to the console.
( Vue evaluates whatever is in between {{ }} as an expression ).
Solution
I suppose, you can either use the deals property directly in html as shown below without using a computed property
<div class="dials__column" v-for="(el, index) in deals">
<div class="dials__header">
<div>{{el.title}}</div>
<div>сделок: <span class="dials__cnt">{{ el.items.length }}</span>, <span></span> руб</div>
</div>
----------- rest of the code
or you can create a computed property based on deals data property and use that to loop in html using v-for.
Problem 2
I don't think below code is valid php string. although it becomes irrelevant if you use first solution above.
<?php
foreach ($deals as $k=>$v) {
echo 'list_'.$v->id.'_deals_cnt: function() {return this.deals['.$k.'].items.length},';
}
?>
the ' inside ['.$k.'] should be escaped.
Solution
echo 'list_'.$v->id.'_deals_cnt: function() {return this.deals[\'.$k.\'].items.length},';

Related

Vue js: How to form validate an array of strings with vuelidate and display the error on each input

I have a vue project in which I collect test answers with forms, I want to have validate each input with { required } but I fail to do so. I have tired the following:
<form class="forms-test"
v-for="(testItem, index) in testItems"
:key="testItem.block"
>
<div class="task-no-picture">
<h4>{{ t("task") }}: {{ t("choose") }}</h4>
<p>
{{ testItems[index].task }}
</p>
<p v-if="v$.studentAnswers.$error">
{{ v$.studentAnswers.$errors[0].$message }}
</p>
<div class="true-false">
<RadioGroup
v-model="studentAnswers[index]"
:options="answerOptionsEn"
vertical
:name="String(index)"
/>
</div>
</div>
</form>
This is the valdations section:
validations() {
return {
studentAnswers: {
required,
},
};
};
I have tried without the foreach loop but the result is the same and I can not figure out a way to get the results I need.

Can't display datetime from v-for

I'm trying to show the datatime in a v-for, but it just keeps showing the same time over and over.
Is there a way to do this?
v-for -
<div class="location-box-container">
<ul class="location-box-list">
<ol v-for="(location, index) in lineStringData" :key="lineStringData.id">
<p class="locations">{{ location_time }} New Location</p>
</ol>
</ul>
</div>
JS -
data() {
return {
location_time: new Date().toLocaleTimeString(),
}
},
Use a method to lookup time. Not sure where you are storing the time, but you can look up timezone from coords if needed.
<div class="location-box-container">
<ul class="location-box-list">
<ol v-for="(location, index) in lineStringData" :key="lineStringData.id">
<p class="locations">{{ getTime(location) }} New Location</p>
</ol>
</ul>
</div>
methods: {
getTime(location) {
// lookup your timezone, etc here.
return new Date(location.theTime).toLocaleTimeString()
}
}

How can I add a task to a list in my Vue 2 to-do app?

I am trying to add a task to a tasklist in Vue based on the input and add task button, but I keep getting the error "taskList is not defined". Does anybody see how to fix this problem? The code is as following:
<template>
<div id="input">
<form>
<input v-model="task.name">
<button v-on:click="addTask" v-bind:value="task.name">+</button>
</form>
<ol>
<div v-for="task in taskList" :key="task.id">
{{ task.name }}
<div v-if="task.completed">
<h2> Done </h2>
</div>
<div v-else>
<h2> Not done</h2>
</div>
</div>
</ol>
</div>
</template>
<script>
export default {
name: 'AddTask',
data: function() {
return {
taskList: [
{
name: 'task', completed: false, id: 3
}
] }
},
methods: {
addTask: function (task) {
taskList.push(task);
alert('test');
}
}
}
</script>
Ps. any other Vue tips are welcome as well.
You need to separate out your taskList and the current task you're adding, decouple it as a new object, then add it to your taskList array.
When referring to items in your data object you need to use the this keyword – e.g this.taskList rather than taskList:
new Vue({
el: "#app",
data: {
id:1,
taskList: [],
currentTask:{
completed:false,
name:'',
id:this.id
}
},
methods: {
addTask: function() {
let newTask = {
completed:this.currentTask.completed,
name:this.currentTask.name,
id:this.currentTask.id
}
this.taskList.push(newTask);
this.id++;
//alert('test');
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="input">
<ol>
<li v-for="task in taskList" :key="task.id">
{{ task.name }}
<input type="checkbox"
:checked="task.completed"
#change="task.completed = !task.completed">
<span v-if="task.completed">
Done
</span>
<span v-else>
Not Done
</span>
</li>
</ol>
<input type="text" v-model="currentTask.name">
<button v-on:click="addTask">+</button>
</div>
</div>
From what I see in your template you use tasklist but you define it as taskList You will want to make sure your names are in the same case. Usually you'll see camelCase in vue, but other popular ones are snake_case and PascalCase

How to get data from JSON? My v-for loop is not working

I'm trying to get data from a external json but the v-for loops does not work. Previously, with the same code I was able to show the data I don't know whats happens now.
This is the code i'm using:
`
<div class="row">
<div class="col-sm-4">
<h1>Llista Valors</h1>
<div class="card" style="margin-bottom: 2%" v-for="dada in list">
<div class="card-header">
Hora: {{dada.lists.hora}}
Preu: {{dada.lists.preu}}
</div>
</div>
</div>
<div class="col-sm-8">
<h1>JSON</h1>
<pre>
{{ $data }}
</pre>
</div>
</div>
</div>`
`
var url = "http://172.17.100.3/api/tarifa2.php";
new Vue({
el: '#main',
created: function () {
this.getApi();
},
data: {
lists: []
},
methods: {
getApi: function () {
this.$http.get(url).then(function (response) {
this.lists = response.body.valors;
});
}
}
});
</script>`
This is what i get:
Your data should be called list:[], not lists:[] to match your template. Or rename your template to in lists.
For each dada in lists, there is no dada.lists.hora or dada.lists.preu. There is only dada.preu or dada.hora.
Each dada in lists is like saying lists[0] (or whatever index).
So try changing the template to just {{data.hora}} etc as needed (after doing the list/lists adjustment per above).

How to filter some vuex data in response to a select change

I'm new to VueJS and still trying to understand all of the constructs. I have a Vuex store and that has several arrays in the state. In a view that uses the vuex store through a computed property, I need to filter the data from the store when a select changes. I don't understand how to wire the select to the officeProjections data in the store.
<select id="busyness"
name="busyness"
class="form-control mt-1"
v-model="workloadLevels"
##change="onWorkloadFilterChange($event)">
<option v-for="wl in workloadLevels" v-bind:value="wl.id">{{ wl.description }}</option>
</select>
<div v-for="op in officeProjections" class="mt-1">
<div class="card">
<div class="card-body">
<h3 class="card-title">{{ op.consultantName }}</h3>
<p>{{ op.workloadLevel }} <button type="button" v-bind:id="op.ConsultantId" class="btn btn-lg btn-info" data-toggle="popover" data-placement="right" v-bind:data-content="op.comment"></button></p>
<p>{{ op.office }}</p>
</div>
</div>
</div>
The model bound to the select cannot be the same as the element in the store serving the arrays, in this case you have v-model="workloadLevels" and `v-for="wl in workloadLevels".
You're going to need a separate model for the selected value:
v-model="selectedWorkloadLevel"
And create that property selectedWorkloadLevel in your Vuex store.
I would not make an action, just a mutation, and I would make it generic:
SET_VALUE: function(state, payload) {
Object.keys(payload).forEach((key) => {
if (state.hasOwnProperty.call(key)) {
state[key] = payload[key]
}
})
}
Then add a get and set computed value for your selectedWorkloadLevel:
get selectedWorkloadLevel() {
return this.$store.getters['selectedWorkloadLevel']
}
set selectedWorkloadLevel(value) {
this.$store.commit('SET_VALUE', { selectedWorkloadLevel: value })
}
Then remove the #change handler and update your v-model:
v-model="selectedWorkloadLevel"