Error setting default accordion item in class condition - vuejs2

In my laravel 5.7 / Vuejs ( vue": "^2.6.10" ) / "bootstrap": "^4.3.1" application
using accordion I want in debugging purpose show 1 block openec with template like:
<div :id="'collapse'+nextStateWithRegion.id" v-bind:class="'collapse'+{ ' show' : nextStateWithRegion.id == debugging_state_id }" :aria-labelledby="'heading'+nextStateWithRegion.id"
data-parent="#accordion_hostels_by_location">
<div class="card-body">
<!--{{ nextStateWithRegion.regionsOfStateArray }}-->
<ul>
<li v-for="nextRegionOfState, index in nextStateWithRegion.regionsOfStateArray" :key="nextRegionOfState.id">
<!--nextRegionOfState::{{ nextRegionOfState }}-->
<router-link :to="{ name: 'hostelsByRegion', params: { region_id: nextRegionOfState.id, state_id : nextRegionOfState.state_id } }"
class="nav-link">{{ nextRegionOfState.name }}
<small>( {{ nextRegionOfState.related_common_hostels_count }} hostels with {{ nextRegionOfState.related_featured_hostels_count }}
featured)</small>
</router-link>
</li>
</ul>
</div>
</div>
but result is different, as I see not ‘ show’ string added to the class, but ‘[object Object]’ :
https://imgur.com/a/YWenuxh
Which way is correct ?
Thanks!

Related

Creating pagination component

I am trying to create pagination component. For e.g if my API returns "pages": 9
For example, if I have 9 pages, I want to cut the list at 5 and add three dots like on the image. I want to be able to provide at which index I can cut the list. Whats the best way to do this? I am approaching this wrong?
<div v-for="index in pages" class="flex">
<button>{{index}}</button>
</div>
Assuming you receive cutIndex and apiPages as props to your component, then your template could look something like the following:
<div v-for="page in Math.min(cutIndex, apiPages)" class="flex">
<button>{{page}}</button>
</div>
<template v-if="cutIndex < apiPages">
<div class="flex">
<button>...</button>
</div>
<div class="flex">
<button>{{apiPages}}</button>
</div>
</template>
this code works for me, and here is the key part
<template>
...
<template v-for="index in pages"
v-if="(index < 4 || (length - index) < 3) || Math.abs(index - value) < 2">
<span v-if="index === (length - 2) && value < (length - 4)">
...
</span>
<button #click.prevent="updatePage(index)">
{{ index }}
</button>
<span v-if="(index === 3 && value > 5)">
...
</span>
</template>
...
</template>
the result:
<template>
<nav class="flex items-center justify-center" role="pagination">
<!-- go to previous page -->
<a :key="`${$route.name}-arrow-${value > 1 ? value - 1 : 1}`"
:href="getFullPath(value > 1 ? value - 1 : 1)"
:title="$t('previous_page')"
#click.prevent="updatePage(value > 1 ? value - 1 : 1)"
:disabled="value === 1"
class="arrow pop-btn default rounded-sm"
v-waves>
<i class="mdi-chevron-left mdi"></i>
</a>
<template v-for="index in length"
v-if="(index < 4 || (length - index) < 3) || Math.abs(index - value) < 2">
<span v-if="index === (length - 2) && value < (length - 4)">
...
</span>
<a :href="getFullPath(index)"
:title="$t('page_index', {index: index})"
#click.prevent="updatePage(index)"
class="pop-btn number default rounded-sm"
:class="{
'active': index === value
}"
v-waves>
{{ index }}
</a>
<span v-if="(index === 3 && value > 5)">
...
</span>
</template>
<!-- go to next page -->
<a :href="getFullPath(value === length ? value : value + 1)"
:title="$t('next_page')"
#click.prevent="updatePage(value === length ? value : value + 1)"
:disabled="value === length"
class="arrow pop-btn default rounded-sm"
v-waves>
<i class="mdi-chevron-right mdi"></i>
</a>
</nav>
</template>
<script type="text/javascript">
export default{
emits: ['update:value],
props: {
length: {
required: true,
type: Number
},
// the page filter
value: {
required: true,
type: Number
}
},
methods: {
updatePage(index){
this.$emit('update:value', index);
},
getFullPath(page){
let query = {...this.$route.query};
page === 1 ? delete query.page : query.page = page;
return this.$router.resolve(
this.r({
query: query,
name: this.$route.name,
params: this.$route.params
})
).href;
}
}
}
</script>
by the way, <a> may better than <button> for SEO

Accessing nested objects in Vue

I am only able to access currentView and subTask, but not subTasks2. Although I'm following the same approach. I want to access the array of objects branches and report in the response. Any hint, please?
[
{
"id": "sss",
"name": "TestDemo",
"visibility": "ss",
"projects": [
{
"name": "ss",
"branchs": [
{
"name": "master",
"state": "none",
"report": {
"branchName": "master",
"projectName": "ss",
"organizationName": "TestDemo",
"failedRuns": 0,
"totalRuns": 0,
"successRunsPercentage": 100
}
}
]
}
]
}
]
Template vuejs (First two binds are working fine). I still want to access branchs and report
<div id="ID1">
<ul>
<li v-for="currentView in responseTest" :key="currentView.id" >
{{ currentView.name }} - {{ currentView.visibility }}
<ul>
<li v-for="subTask in currentView.projects " :key="subTask.id" >
{{ subTask.name }} - {{ subTask.branchs }}
</li>
</ul>
<ul>
<li v-for="subTask2 in subTask.branchs " :key="subTask2.id" >
{{ subTask2.name }} - {{ subTask2.state }}
</li>
</ul>
</li>
</ul>
</div>
The issue you're facing is that subTask is undefined in your third v-for due to incorrect nesting.
You can only access your variables assigned from the v-for inside child components of that element.
The element your subTask2 in subTask.branchs loop needs to be a child of the element that has the subTask variable.
For example:
<div id="ID1">
<ul>
<li v-for="currentView in responseTest" :key="currentView.id">
{{ currentView.name }} - {{ currentView.visibility }}
<ul>
<li v-for="subTask in currentView.projects" :key="subTask.id">
{{ subTask.name }} - {{ subTask.branchs }}
<ul>
<li v-for="subTask2 in subTask.branchs" :key="subTask2.id">
{{ subTask2.name }} - {{ subTask2.state }}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
You may need to play about with the structure and formatting to make it look right but that example should be runnable.

Vue.js - How to display all property keys and nested property values?

Couldn't find a better title, my issue is hard to describe in one sentence. I'm trying to loop through an imported object generated by some third party package, but its structure is problematic:
obj: {
"name1": {
"property1": "value1",
"property2": "value2",
},
"name2": {
"property1": "value3",
"property2": "value4",
},
"name3": {
"property1": "value5",
"property2": "value6",
}
}
I want to display not just property1 and property2 but also the name preceding these:
- name1
value1
value2
- name2
value3
value4
...
This is the code I have so far:
<ul>
<li v-for="(item, i) in obj" :key="index">
{{ item.property1 }}
<br>
{{ item.property2 }}
</li>
</ul>
How can I display the name as well, given this object' odd structure?
JSFiddle
Just add key property in your v-for loop and render it :
<li v-for="(item,key, i) in obj" :key="index">
{{key}}
<br>
{{ item.property1 }}
<br>
{{ item.property2 }}
</li>
Loop the object key with Object.keys(), and display the object value from the key with another v-for
<script src="https://unpkg.com/vue"></script>
<div id="app">
<ul>
<li v-for="(item, i) in Object.keys(obj)" :key="index">
{{ item }}
<ul>
<li v-for="(property, key) in obj[item]" :key="property">
{{ key }} -> {{ property }}
</li>
</ul>
</li>
</ul>
</div>

Set focus to first item in v-for using vue

I have a vue app and I'm trying to set the focus to the first item in my v-for list but struggling
HTML
<div class="input-group-append">
<button class="btn btn-light" type="submit" style="border: 1px solid lightgray" #click.prevent="findTest">
<i class="fas fa-search"></i>
</button>
</div>
<div v-if="this.Tests.length >= 2" class="list-group accList">
<a v-for="(test, i) in tests" :key="i" class="list-group-item list-group-item-action" :ref="i" :class="{ 'active': i === 0 }" #click.prevent="selectTest(test)">
{{ test.test1 }} ({{ test.test2 | capitalize }})
</a>
</div>
Note the word 'test' has replaced my actual values
I have tried using the following in my method which is called on button click but I keep getting get an error
methods: {
findTest() {
axios.get(END_POINT).then((response) => {
...SOMEOTHER CODE
//this.$refs.0.$el.focus()
//this.$refs.0.focus();
//this.$refs.a.$el.children[0].focus();
}
}
}
Error
I am relativly new to vue but I have been able to set my focus using:
this.$refs.[INPUT_NAME].$el.focus()
But it doesn't like me using a number
this.$refs.0.$el.focus() //0 being the index number
As WebStorm complains saying:
Expecting newline or semicolon
console.log(this.$refs)
When using v-for, ref maybe array of refs.
Template: use ref="tests" instead of :ref="i"
<a v-for="(test, i) in tests" :key="i" class="list-group-item list-group-item-action" ref="tests" :class="{ 'active': i === 0 }" #click.prevent="selectTest(test)">
{{ test.test1 }} ({{ test.test2 | capitalize }})
</a>
Script
this.$refs.tests[0]
I guess its undefined because you try to access the element while the v-for loop didnt finished its rendering
Try this:
methods: {
findTest() {
axios.get(END_POINT).then((response) => {
...SOMEOTHER CODE
this.$nextTick(()=> {
//put your code here
//this.$refs.0.$el.focus()
//this.$refs.0.focus();
//this.$refs.a.$el.children[0].focus();
})
}
}
}
Put your code into $nextTick() that should ensure that its get executed when the loop is done

Printing key in Vue.js iteration

I have array like below
data() {
return {
shoppingItems: [
{name: 'apple', price: '10'},
{name: 'orange', price: '12'}
]
}
}
I am trying to iterate like below
<ul>
<li v-for="item in shoppingItems">
{{ item.name }} - {{ item.price }}
</li>
</ul>
I am getting output like below
apple - 10
orange - 12
But I would like to get output like below
name - apple, price - 10 //I would like to print key dynamically
name - orange, price - 12
You can use (key,value) pair in for loop
var app = new Vue({
el:'#app',
data() {
return {
shoppingItems: [
{name: 'apple', price: '10'},
{name: 'orange', price: '12'}
]
}
}
});
li span{
text-transform: capitalize;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in shoppingItems">
<span v-for="(v,i,count) in item">{{i}} - {{v}}<span v-show="count<(Object.keys(item).length-1)
">, </span></span>
</li>
</ul>
</div>
You can iterate over the keys/values with this :
<div v-for="(value, key) in object">
{{ key }} - {{ value }}
</div>
You can also have the index of the current key :
<div v-for="(value, key, index) in object">
{{ key }} - {{ value }}
// if index > 0, add comma
</div>
Use default way of Vue to do this
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
Easy and simple
Object.Keys(Object) returns an array containing all the key of the object. Now you can use index to fetch the desire key -
<ul>
<li v-for="item in shoppingItems">
{{ Object.keys(item).indexOf(0) }} : {{ item.name }} - {{ Object.keys(item).indexOf(1) }} : {{ item.price }}
</li>
</ul>
Let's assume that we have a person array or list which contain person object persons:
[{name:'Suru', age:4, hairColor:'red'}, {name: 'Sofia', age:'5', hairColor:'green'}]
Now let's loop through person list and get key, value, and index
new Vue({
el: '#app',
data: {
persons: [
{name: 'Suru', age: 4, hairColor: 'red'},
{name: 'Sofia', age: '5', hairColor: 'green'}
]
}
});
<script src="https://unpkg.com/vue"></script>
<div id='app'>
<ul>
<li v-for="person in persons">
<span v-for="(value, key, index) in person">
{{key}}: {{value}} - {{index}}<br>
</span>
<br>
</li>
</ul>
</div>