Unable to get index of array - vue.js

I am trying to get the current index of an array when using v-for like so:
<tr v-for="(item,index) in timetable">
Index: #{{index}}
<td>#{{ item.subject }}</td>
<div v-if="index == timetable.length - 1">
<td>#{{ item.lesson_end }}</td>
</div>
<div v-else>
<td>#{{ item.lesson_start }}</td>
</div>
</tr>
But I only get the error message:
[Vue warn]: Property or method "index" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
Why does it claim that index is not defined, according the docs this should be valid?

The problem is solely due to your invalid HTML structure. Vue's render function is not able to interpolate the result correctly and thus, you get that error.
Try something like
<tr v-for="(item,index) in timetable">
<td>Index: #{{ index }}</td>
<td>#{{ item.subject }}</td>
<td v-if="index == timetable.length - 1">#{{ item.lesson_end }}</td>
<td v-else>#{{ item.lesson_start }}</td>
</tr>
http://jsfiddle.net/Lrvdjxpq/

Related

Using v-for in a table

I have a table is populated with some info and I would like to format the table like the picture
Unfortunately the excel sheet which I have no control over is formatted so:
I want any row that has only a Equipment type to span whole row. All other rows should appear as normal table row.
I am using following vue template:
<table>
<caption>
SHS Scrap Table
</caption>
<thead>
<tr>
<th>Make</th>
<th>Model #</th>
<th>Bar Code</th>
<th>Serial #</th>
<th>Location</th>
<th>Condition</th>
</tr>
</thead>
<tbody v-for="item in scrapDataEmptyRowsRemoved" :key="item">
<tr v-if="item['Equipment Type']">
<td class="equipt-type" colspan="6">
Equipment Type - {{ item["Equipment Type"] }}
</td>
</tr>
<tr v-else>
<td>{{ item["Make"] }}</td>
<td>{{ item["Model #"] }}</td>
<td>{{ item["Bar Code"] }}</td>
<td>{{ item["Serial #"] }}</td>
<td>{{ item["Location"] }}</td>
<td>{{ item["Condition"] }}</td>
</tr>
</tbody>
</table>
The only problem is that looking in Devtools I see that every row has a Tbody which is not semantically correct. Any idea's on how to correct this. If I use a container around the v-if v-else all formatting breaks down.Thanks...
Update the only problem is Vite is objecting to moving :key attribute to the v-else:
I dont what other unique key they want.
Update II - Ok apparently if I use different object keys Vite is ok with that ie :key="item['Equipment Type'] and on v-else :key="item['Make']. Does that seem correct?
You can move the v-for in a template tag, that won't be rendered in the DOM.
<tbody>
<template v-for="item in scrapDataEmptyRowsRemoved" :key="item">
<tr v-if="item['Equipment Type']">
<td class="equipt-type" colspan="6">
Equipment Type - {{ item["Equipment Type"] }}
</td>
</tr>
<tr v-else>
<td>{{ item["Make"] }}</td>
<td>{{ item["Model #"] }}</td>
<td>{{ item["Bar Code"] }}</td>
<td>{{ item["Serial #"] }}</td>
<td>{{ item["Location"] }}</td>
<td>{{ item["Condition"] }}</td>
</tr>
</template>
</tbody>

How to call method in loop using vuejs

I already call method in v-for, it works. But I get
[Vue warn]: You may have an infinite update loop in a component render function.
How to solve this?
This is my code:
<tr v-for="(item,index) in all_data" :key="index">
<td>{{ item.name }}</td>
<td colspan="2">{{ toMakeLocalString(item.data_trx.total_penjualan) }}</td>
<td>{{ roundDataPercentPerline(item.data_trx.total_penjualan,all_data_trx.penjualan) }}</td>
{{ resetVal() }}
<template v-for="(itemBodyJum,indexBodyJum) in arrHeader">
<template v-if="itemBodyJum == item.data_provider[incrementI].denom">
<td :key="indexBodyJum+item.data_provider[incrementI].jumlah_trx">{{ toMakeLocalString(item.data_provider[incrementI].jumlah_trx) }}</td>
{{ incVal(incrementI) }}
</template>
<template v-else>
<td :key="indexBodyJum+index">0</td>
</template>
</tr>
My method:
incVal(val, flagcond) {
console.log(this.flagInc+'---1')
if(this.flagInc == false) {
this.flagInc = true
console.log(this.flagInc+'---2')
this.incrementI = val + 1
}
},
resetVal() {
this.flagInc = false
this.incrementI=0
}
Your problem is that you change the incrementI variable during the V-FOR. Try to use something else instead - e.g. indexBodyJum or indexBodyPen.

building a hyperlink in a Vuetify Datatable - maybe v-bind?

I'm close to where I need to go but not close enough. This is my code
<td>
<a href="https://www.ncbi.nlm.nih.gov/pubmed/"
{{item.pmid}} target="_blank">{{ item.pmid }}</a>
</td>
<td>{{ item.year }}</td>
<td>{{ item.title }}</td>
<td>{{ item.authors }}</td>
<td>{{ item.article }}</td>
<td>{{ item.journal }}</td>
<td>{{ item.rcr }}</td>
<td class="text-xs-right">{{ item.percentile }}</td>
If I take out the href {{item.pmid}} it will go to the web page in a new window. However I need to add the item.pmid value to the end of the href string so it will go to an exact page. If I leave it the way it is now I get an error saying 'Element': '{{' is not a valid attribute name. Is there someway that I can get the value concatenated to the string?
OK-- I've found this:
How to put variable in a href on the vue js 2?
But still not sure about how to us v-bind
The best way to do this, if anyone is still wondering, is to use dynamic rows
They work like this:
<v-data-table
:headers="tableHeaders"
:items="tableItems"
>
<template v-slot:item.link="{ item }">
<a :href="item.link">Link</a>
</template>
</v-data-table>
got it--
<td>
<a
:href="'https://www.ncbi.nlm.nih.gov/pubmed/' + item.pmid"
target="_blank"
>{{ item.pmid }}</a>
</td>

vue.js: Variables in attributes [duplicate]

I have a route in Laravel that requires an id as a parameter.
Route::get('/example/{id}', ExampleController#index)
If I had passed the data from the Laravel controller to the view value I would pass it like this:
Click
But my id is a vue value:
<tr v-for="item in items">
<td>#{{ item.id }}</td>
<td>#{{ item.name }}</td>
<td>#{{ item.number }}</td>
<td>#{{ item.address}}</td>
<td v-if="item.status==0">Click</td>
</tr>
Which is the correct way to do this?
You can just use v-bind for this, like following:
<a :href="'/example/' + item.id" class="button success">Click</a>

Group multiple td in parent element for child component

I have a layout similar to this:
My parent component is this:
<!-- Parent -->
<table>
<thead>
<tr>
<th>ID</th>
<th>Some</th>
<th>Column</th>
<th>Names</th>
</tr>
</thead>
<tbody>
<tr v-for="thing in things">
<td>{{ thing.id }}</td>
<my-child-component :thing="thing"></my-child-component>
</tr>
</tbody>
</table>
And my child component is like this:
<!-- Child Component -->
<template>
<td>{{ thing.foo }}</td>
<td>{{ thing.bar }}</td>
<td>{{ thing.baz }}</td>
</template>
I know you're required to have a single top level element in Vue (2.0), but I wondered if there's an "invisible" element that I can use. I know you can use v-for in a <template> tag but that won't work in my case.
Or, is there some wrapper that isn't going to break everything. I tried div/span etc but it was horrible and non-semantic.
Basically what I want is for the table header columns to line up with the tbody contents (I have been down the road of having a td with colspan set on it and putting a table inside that, but the columns don't always line up.
PS The real thing is much more complex than the example above, and I am presenting tabular data so don't want to hack about with css to reproduce a table.
Since you say that "the real thing is more complex", it's hard to tell if this will work in your case, but one way to do it could be something like this:
<tbody>
<my-child-component :things="things"></my-child-component>
</tbody>
And then in the child component:
<tr v-for="thing in things">
<td>{{ thing.id }}</td>
<td>{{ thing.foo }}</td>
<td>{{ thing.bar }}</td>
<td>{{ thing.baz }}</td>
</tr>
Not sure if this would work in your scenario?