Display multiple checkbox in table format using <v-for> and <v-checkbox> in Vuetify? - vue.js

I'm using the
VuetifyJs
for VueJS and I'm trying to display checkbox in table format from an array of objects.
Desired Output shown below :
When 'All Users' is checked all the checkboxes should be checked.
I created a row layout and divided this row into two flex boxes so I have the structure of row with two columns. I loop using 'v-for' and for every row display the value of the current index and the next index. But the last entry is repeated the next time the loop is iterated. The closest I could reach is as shown below:
CodePen Url: https://codepen.io/dhnsh/pen/ZRMgoE
I also tried to use table instead of layout and flex but could not make it. In the codepen I use the function 'checkLength' to get the next index because incrementing the 'index' with pre-increment operator gives error(probably due to array goes out of bounds).
I am struggling with the below queries :
1) How can we display the desired output in Vuetify ?
2) Is there anyway to iterate 'v-for' with increment of "2" like we can do in Javascript ?
ex:
for(var i=0;i<array.length();i += 2)

You should put v-layout outside of v-for
<div class="mr-4 ml-4 whiteback userGroupHeight">
<v-layout row wrap>
<v-flex v-for="(category,index) in types" :key="types[index].text" xs6>
<v-checkbox light :label="category.text" v-model="category.selected">
</v-checkbox>
</v-flex>
</v-layout>
</div>
then you don't need to use checkLength method.
Demo: https://codepen.io/ittus/pen/ZRqYME

Related

Bootstrap Table row-clicked event

I'm using a <b-table> component in a Vue project and I need to define a function to be triggered when a row is clicked. I heard that there is a #row-clicked property in b-table so I tried to use it and I can put simple functions inside of it, I mean I can get console prints etc but nothing more complicated...
I want two functions to be executed when a row is clicked. The functions are now bound to a button inside of every row, but I dont want use it like this, I just need to click the related row to make them work. Here is the current version of the b-table component;
<b-table
:items="displayByType"
:fields="displayColumn"
responsive="sm"
:per-page="perPage"
:current-page="currentPage"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
:filter="filter"
:filter-included-fields="filterOn"
#filtered="onFiltered"
hover
#row-clicked="test"
>
And here is the two functions that I want to be triggered when a row is clicked...
toggleRightBar(){
document.body.classList.toggle("right-bar-enabled");
}
changeRightBarContent(row){
this.$store.dispatch("rightbar/changeRightBarInfo", tableData[row]);
},
There is a JavaScript folder that I export column names and row data. I also a have Rightbar, when a row is clicked, I want to enable the rightbar so that the user can see detailed information about that specific row.
At last, here is the button that I use to make these two functions work;
<template #cell(detail)="row">
<button #click="toggleRightBar(); changeRightBarContent(row.index);" class="btn btn-outline-primary toggle-right">
<i class="bx bx-detail toggle-right"></i>
</button>
</template>
Basically, I dont want to use this button, instead, I want to click the row itself. Every row's rightbar information will be uniqe, my function does that. I just dont know how to use these 2 functions inside #row-clicked
Thanks in advance.
The row-clicked event will pass 3 parameters to your function.
The first being the item specific to the row that was clicked. The second will be the index of the row, and the third is a native click event.
This means you can use the arguments keyword to get the index and pass it to your function.
#row-clicked="toggleRightBar(); changeRightBarContent(arguments[1])".
Alternatively you can create a third method which will call the other two.
<b-table #row-clicked="onRowClicked" />
{
onRowClicked(item, index, event) {
this.toggleRightBar();
this.changeRightBarContent(index);
}
}
You can read more about the #row-clicked event on the docs component reference section.
https://bootstrap-vue.org/docs/components/table#comp-ref-b-table-events

How do i add color to an entire Vuetify Data Table row with dynamic headers

Good day.
I have a data-table divided by groups with dynamic headers that change depending on whatever months the user choose to obtain information from, so i want to get information from the months of January until April i'll have 5 columns, one with the name of my classifications and 4 related to the months i am searching for.
every group has a row called total that summarizes the expenses of each group for each month and i want to be able to color this entire row with a color of my choosing. How would i go about that, especially when i have dynamic headers that change whenever the user searches for a time period?
<v-data-table
dense
:headers="headers"
:items="classifications"
item-key="classification"
group-by="classification_group"
disable-sort
hide-default-footer
disable-pagination
class="elevation-1"
>
<template v-slot:group.header="{items, isOpen, toggle}">
<th colspan=1000000>
<v-icon #click="toggle"
>{{ isOpen ? 'mdi-minus' : 'mdi-plus' }}
</v-icon>
{{ items[0].classification_group }}
</th>
</template>
</v-data-table>
One solution is to apply a class to the "total" row's tr element and have CSS that is applied to this class.
So in my v-data-table template, I have a v-if that detects if the tr element is for a "total" row and, if so, applies a table-row-total class.
Then, in that component's <style> section I apply something like:
.my-table-name .v-data-table tr.table-row-total {
background-color: #ffff00 !important;
}
You may want to double-check the Vuetify data tables API, but to the best of my knowledge, I don't know of a more sophisticated way in Vuetify to handle styling 'special case' rows in a datatable -- so, the method above worked fine for me.

Dynamically display certain column data from query object using vuetify

I have a query Object that returns 357 columns (e.g, fullRecord). For a certain portion of my UI, I want to query through a subset of about 125 of those items and display them in a list. I have the column names of those items I want to display in an array (e.g., colsWanted).
I am trying to figure out how to dynamically iterate through the "colsWanted" array and display the appropriate "fullRecord.colsWanted(Item)" in the vuetify interface. I've tried what feels like a million different iterations of this but here is the latest which shows an error:
<v-flex v-for="(value, index) in colsWanted" :key="value">
<v-card flat>
<span v-if="fullRecord[value] in fullRecord">
<strong>{{ index }}. {{ fullRecord[value] }}</strong>
</span>
<span v-else class="error--text">Not Available</span>
</v-card>
</v-flex>
I actually get no errors at all from this; but no results are displayed when they should in fact return results.
Thanks in advance for any assistance.
Your object key selection is wrong:
<span v-if="fullRecord[value] in fullRecord">
fullRecord[value] will retrieve the value of the value key, which will not be in fullRecord.
What you should be using is:
<span v-if="value in fullRecord">
or
<span v-if="fullRecord.hasOwnProperty(value)">
Also I would rename value to key since thats what it actually is.

bootstrap-vue toggle expand table row

This seems to remain unanswered so here is another attempt at a solution.
Currently in bootstrap-vue, I am rendering a b-table. I would like to improve this by having the ability to select a row and collapse/expand an extra div/row/etc to show further information.
In the below snippet you will see what I am trying. The problem is that I can't seem to get the expanded data to span the number of columns in the table. I have tried adding <tr><td colspan="6"></td></tr> but it doesn't seem to span like I would expect. Any workarounds for this? Thanks.
<b-table
:items="case.cases"
:fields="tableFields"
head-variant="dark">
<template
slot="meta.status"
slot-scope="data">
<b-badge
v-b-toggle.collapse1
:variant="foobar"
tag="h6">
{{ data.value }}
</b-badge>
</template>
<template
slot="#id"
slot-scope="data">
<span
v-b-toggle.collapse1>
{{ data.value }}
</span>
<b-collapse id="collapse1">
Collapse contents Here
</b-collapse>
</template>
</b-table>`
Sounds like you could use the Row Details slot:
If you would optionally like to display additional record information (such as columns not specified in the fields definition array), you can use the scoped slot row-details
<b-table :items="case.cases" :fields="tableFields" head-variant="dark">
<template slot="meta.status" slot-scope="data">
<b-button #click="data.toggleDetails">
{{ data.value }}
</b-button>
</template>
<template slot="row-details" slot-scope="data">
<b-button #click="data.toggleDetails">
{{ data.detailsShowing ? 'Hide' : 'Show'}} Details }}
</b-button>
<div>
Details for row go here.
data.item contains the row's (item) record data
{{ data.item }}
</div>
</template>
</b-table>
There is a good example in the docs at https://bootstrap-vue.js.org/docs/components/table#row-details-support
I (think) I had the same issue, and I came up with a solution which leverages the filtering functionality of the bootstrap-vue <b-table> to achieve the effect of expanding and collapsing rows.
There's a minimal example in a JSFiddle here:
https://jsfiddle.net/adlaws/mk4128dg/
Basically you provide a tree structure for the table like this:
[
{
columnA: 'John', columnB:'Smith', columnC:'75',
children:
[
{ columnA: 'Mary', columnB:'Symes', columnC:'46' },
{ columnA: 'Stan', columnB:'Jones', columnC:'42' },
{ columnA: 'Pat', columnB:'Black', columnC:'38' },
]
}
]
The tree is then "flattened" out to rows which can be displayed in a table by the _flattenTreeStructure() method. During this process, the rows are also annotated with some extra properties to uniquely identify the row, store the depth of the row (used for indentation), the parent row of the row (if any) and whether or not the row is currently expanded.
Once this is done, the flattened structure can be handed to the <b-table> as it is just an array of rows - this is done via the computed property flattenedTree.
The main work now is done by the _filterFunction() method which provides custom filtering on the table. It works off the state of the expandedRowIndices property of the filterObj data item.
As the expand/collapse buttons are clicked, the row index (as populated during the flattening process) is inserted as a key into expandedRowIndices with a true or false indicating its current expanded state.
The _filterFunction() uses this to "filter out" rows which are not expanded, which results in the effect of expanding/collapsing a tree in the table.
OK, so it works (yay!), but...
it's not as flexible as the base <b-table>; if you want to show different columns of data, you'll need to do some work and to re-do the <template slot="???"> sections for the columns as required.
if you want to actually use filtering to filter the content (with a text search, for example) you'll need to extend the custom filter function to take this into account as well
sorting the data is not something I had to do for my use case, and I'm not sure how it would work in the context of a tree structure anyway - maintaining the tree's parent/child relationships while changing the order of the rows around would be... fun, and I suspect this would be a nice challenge to implement for someone who is not as time poor as me. ;)
Anyway, I hope this is of use to someone. I'm reasonably new to Vue.js, so there may be a better way to approach this, but it's done the job I needed to get done.

In VueJS, v-for doesn't create discrete items when new data is assigned

Currently, when I have a v-for loop like this:
<li v-for="record in records">
<my-vue-list-item :vue-title="record.title"></my-vue-list-item>
</li>
and I update the data driving the v-for (i.e. assign a new value to records), it doesn't actually create new list items based on the new data. It just updates some of the properties on the list item components components.
Here is a JSFiddle illustrating what I'm talking about. Try expanding one of the buttons (e.g. click "Expand Apple"), then click on "Set 2" to see that even when the list items switch, the component stays expanded.
What's the recommended way of getting around this behavior? I want each new list item (when the data is swapped out) to appear like new. (In the fiddle example, which I load a new set, it should not be already expanded.)
You need to let the Vue components know that the item is different. As far as they know, they're still rendering the same element index from the same list.
You can do this by specifying the key in your v-for iterator...
<li v-for="item in items" :key="item">
https://jsfiddle.net/ahxf44jk/21/