How do i add action column with 'edit' and 'delete' buttons? - vue.js

I want to add action column in the table with delete and edit buttons in it. Table in the image is output of the coded below. An action column is needed in the table in order to perform actions i.e edit and delete.
Table
Code for the table
<b-table
responsive
class="mb-0"
head-variant="light"
:items="items"
:current-page="currentPage"
:per-page="perPage"
>
<template #cell(id)="data"> #{{ data.item.id }} </template>
<template #cell(user)="data">
<b-img
:src="require('#/assets/images/users/' + data.item.user.image)"
rounded="circle"
:alt="data.item.user.image"
width="40"
/>
<span class="ml-2 fw-medium"
>{{ data.item.user.first }} {{ data.item.user.last }}</span
>
</template>
<template #cell(team)="data">
<b-img
:src="require('#/assets/images/users/' + data.item.team.teamimg1)"
rounded="circle"
:alt="data.item.team.teamimg1"
width="35"
class="mr-n2 border border-white"
/>
<b-img
:src="require('#/assets/images/users/' + data.item.team.teamimg2)"
rounded="circle"
:alt="data.item.team.teamimg2"
width="35"
class="mr-n2 border border-white card-hover"
/>
<b-img
:src="require('#/assets/images/users/' + data.item.team.teamimg3)"
rounded="circle"
:alt="data.item.team.teamimg3"
width="35"
class="border border-white"
/>
</template>
<template #cell(status)="data">
<b-badge
pill
:class="`px-2 text-white badge bg-${data.item.status.statusbg}`"
>
<i class="font-9 mdi mdi-checkbox-blank-circle"></i>
{{ data.item.status.statustype }}
</b-badge>
</template>
<template #cell(action)="data">
<b-button variant="light" #click="deleteUser(data.item.user.id)">
<feather type="delete" class="feather-sm"></feather>
</b-button>
</template>
</b-table>

I'd suggest you to use the b-dropdown element (more info here). Your table would then have one column with an "action" description and have a b-dropdown button for each row:
<b-table
responsive
class="mb-0"
head-variant="light"
:items="items"
:current-page="currentPage"
:per-page="perPage"
>
<template #cell(id)="data"> #{{ data.item.id }} </template>
<!--......-->
<template #cell(action)="data">
<b-dropdown
right
variant="primary"
>
<template v-slot:button-content>
Select One
</template>
<b-dropdown-item v-on:click="edit(data.item)">
Edit
</b-dropdown-item>
<b-dropdown-item v-on:click="delete(data.item)">
Delete
</b-dropdown-item>
</b-dropdown>
</template>
</b-table>
Then, in your methods, just add:
edit: function(myObject) {
console.log(myObject);
//Do something here
},
delete: function(myObject) {
console.log(myObject);
//Do something here
},
You could also add one column for each edit and delete feature. In this case, simply create a normal b-button and just call the v-on:click="edit(data.item)" and v-on:click="remove(data.item)" the same way it was implemented on the b-dropdown-items

Related

add an icon next to each row in the table using bootstrap vue?

I have a table that uses bootstrap Vue's table. Each row of the table corresponds to an item. My current problem is I need to add an icon next to each row, and display them every time I hover over that row, and then do some function when I click on this icon. But I can't find a way to add an icon. I have tried following the instructions on https://bootstrap-vue.org/docs/components/table with using slots but it only works for #head and #cell. Need an idea on this issue. This is my code and a picture describe my problem
<b-table
ref="table"
class="minh--30 mh--100 overflow-y-auto"
bordered
responsive
:items="items"
:fields="fields"
>
<template #head()="data">
<span>{{ $t(data.field.label) }}</span>
</template>
<template #cell(field)="data">
<span
v-if="data.item.isDrag"
class="d-block p-3"
>{{ data.item.field }}</span>
<b-dropdown
v-else
right
no-caret
variant="white"
class="minw--40 w-100"
menu-class="w-100 mh--24 overflow-auto minw-unset"
>
<template #button-content>
<div
class="flex-center minh--11 text-normal position-relative px-2"
>
<span class="pr-5 word-break text-line-clamp-1">{{ data.item.field }}</span>
<i
class="fas fa-chevron-down position-absolute top-50 end--1 translate-middle-y px-2"
/>
</div>
</template>
<b-dropdown-item
v-for="item in listField"
:key="item.id"
variant="normal py-2"
class="fs-12 fs-xl-15"
#click="selectField(item, data)"
>
<span class="word-break text-line-clamp-1">{{ $t(item.text) }}</span>
</b-dropdown-item>
</b-dropdown>
</template>
<template #cell(action)="data">
<b-dropdown
right
no-caret
variant="white"
class="minw--40 w-100"
menu-class="w-100 mh--24 overflow-auto minw-unset"
>
<template #button-content>
<div
class="flex-center minh--11 text-normal position-relative px-2"
>
<span class="pr-5 word-break text-line-clamp-1">{{ data.item.action }}</span>
<i
class="fas fa-chevron-down position-absolute top-50 end--1 translate-middle-y px-2"
/>
</div>
</template>
<b-dropdown-item
v-for="item in listDropdown"
:key="item.id"
variant="normal py-2"
class="fs-12 fs-xl-15"
#click="selectItem(item, data)"
>
<span class="word-break text-line-clamp-1">{{ $t(item.text) }}</span>
</b-dropdown-item>
</b-dropdown>
</template>
<template #cell(selectCharacter)="data">
<b-dropdown
right
no-caret
variant="white"
class="minw--40 w-100"
menu-class="w-100 mh--24 overflow-auto minw-unset"
>
<template #button-content>
<div
class="flex-center minh--11 text-normal position-relative px-2"
>
<span class="pr-5 word-break text-line-clamp-1">{{ data.item.selectCharacter }}</span>
<i
class="fas fa-chevron-down position-absolute top-50 end--1 translate-middle-y px-2"
/>
</div>
</template>
<b-dropdown-item
v-for="item in listCharacter"
:key="item.id"
variant="normal py-2"
class="fs-12 fs-xl-15"
#click="selectCharacter(item, data)"
>
<span class="word-break text-line-clamp-1">{{ $t(item.text) }}</span>
</b-dropdown-item>
</b-dropdown>
</template>
<template #cell(inputCharacter)="data">
<input
v-model="data.item.inputCharacter"
type="text"
class="form-control h--11 border-0"
>
</template>
<template #cell(startPosition)="data">
<input
v-model="data.item.startPosition"
type="number"
class="form-control h--11 border-0"
>
</template>
<template #cell(characterCount)="data">
<input
v-model="data.item.characterCount"
type="number"
class="form-control h--11 border-0"
>
</template>
<template #cell(needReplace)="data">
<input
v-model="data.item.needReplace"
type="text"
class="form-control h--11 border-0"
>
</template>
<template #cell(replace)="data">
<input
v-model="data.item.replace"
type="text"
class="form-control h--11 border-0"
>
</template>
<template #cell(delete)="data">
<div class="flex-center pt-1">
<input
v-if="!data.item.isDrag"
v-model="data.item.delete"
type="checkbox"
>
</div>
</template>
</b-table>
Based on reading the documentation, the table component wasn't designed for this use case because you are adding icons that are outside of the table itself.
One alternative would be to use the grid system https://bootstrap-vue.org/docs/components/layout#layout-and-grid-system to create one narrow column on the left for the icons and one wide column on the right for the table. In the narrow column, you could create rows that are exactly the height of each row of the table so that the items stay aligned with each row.
Another alternative would be to use the #cell slot, and put an element inside that uses CSS, possibly the transform property (https://www.w3schools.com/cssref/css3_pr_transform.asp), to make the element appear to the left of where it really is.

How to specify when a Vue Component has extra functionality?

I have a table component, and this table component has the ability to select attributes, however I only want this ability to be available when I need it to be, aka not every time it's rendered. How do I do this?
Functionality snippet from Component.vue to only be active when in a certain file ie Component2.vue
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<b-table-column field="columnValue" v-slot="props2" class="attr-column">
<b-table :bordered="false" class="attr-table" :striped="true" :data="props2.row.columnValues">
<b-table-column field="columnName" v-slot="itemProps">
<SelectableAttribute :attr-name="props2.row.fieldClass" :attr-id="itemProps.row.id" :model-id="itemProps.row.id" model-name="NewParticipant">
{{ itemProps.row.value }}
</SelectableAttribute>
</b-table-column>
</b-table>
</b-table-column>
</b-table>
Component.vue
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<b-table :striped="striped" :bordered="false" :data="participants" detailed class="participant-table" :row-class="() => 'participant-row'">
<b-table-column field="primaryAlias" :label="t('participant.table.primary_alias')" v-slot="props">
<template v-if="props.row.primaryAlias">
<SelectableAttribute attr-name="Alias" :attr-id="props.row.primaryAlias.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryAlias.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>
<b-table-column field="primaryEmail" :label="t('participant.table.primary_email')" v-slot="props">
<template v-if="props.row.primaryEmail">
<SelectableAttribute attr-name="Email" :attr-id="props.row.primaryEmail.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryEmail.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>
<b-table-column field="primaryAddress" :label="t('participant.table.primary_address')" v-slot="props">
<template v-if="props.row.primaryAddress">
<SelectableAttribute attr-name="Address" :attr-id="props.row.primaryAddress.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryAddress.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>
*<b-table-column field="primaryPhone" :label="t('participant.table.primary_phone')" v-slot="props">
<template v-if="props.row.primaryPhone">
<SelectableAttribute attr-name="Phone" :attr-id="props.row.primaryPhone.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryPhone.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>*
<b-table-column v-slot="props" cell-class="cell-action">
<slot v-bind="props.row">
</slot>
</b-table-column>
<template slot="detail" slot-scope="props">
<b-table class="attrs-detail-container" :data="tableDataToDataValueCells(props.row)" cell-class="with-bottom-border">
<b-table-column field="columnName" v-slot="props">
<b>{{ props.row.columnName }}</b>
</b-table-column>
<b-table-column field="columnValue" v-slot="props2" class="attr-column">
<b-table :bordered="false" class="attr-table" :striped="true" :data="props2.row.columnValues">
<b-table-column field="columnName" v-slot="itemProps">
<SelectableAttribute
:attr-name="props2.row.fieldClass"
:attr-id="itemProps.row.id"
:model-id="itemProps.row.id"
model-name="NewParticipant"
>
{{ itemProps.row.value }}
</SelectableAttribute>
</b-table-column>
</b-table>
</b-table-column>
</b-table>
</template>
</b-table>
</template>
You can achieve this by using props that you pass while calling that component. That prop could be anything you need. Here is a small example with simple true/false prop:
// Set the prop in your called component, in this case a boolean
props: {
myBoolean: Boolean
}
// Passing the prop from your parent to the component, where it has to be a property, in this case called myBooleanFromParent
<my-component :myBoolean="myBooleanFromParent"></my-component>
// In your component your template changes according to the passed prop from your parent
<template>
<div>
<div v-if="myBoolean">
If myBoolean is true
</div>
<div v-else>
Else, so if myBoolean is false
</div>
</div>
</template>
This is, as stated, a small and simple example. You can pass any kind of data with props. It could also be a object full of data to handle multiple conditions.

Vuetify: Use v-chip-group inside a v-select selection slot

I am trying to add a v-chip-group in a v-select v-slot=selection but am failing.
Due to design requirements, I have to persist some placeholder text in a multi-select but only have so much width for the component. I want the chips to overflow to the right with a scroll interface like the default v-chip-group but can't seem to work it together.
Goal
Current
How can I get the proxy BaseSelect component, which is basically a wrapper for default styling of a v-select, to work as v-chip-group? I also want the chips to work with the deletable-chips prop.
Component
<BaseSelect
multiple
class="flex-0-1-30rem"
localKey="breakdownBy"
:items="localizedBreakdownList"
:value="breakdowns"
:placeholder="$t('select-breakdownBy-label')"
#change="setBreakdowns"
>
<template v-slot:selection="{ item, select, index }">
<span
v-if="index === 0"
class="text--uppercase"
>{{ $t('select-breakdownBy-label') }}</span>
<v-chip color="primary" class="text--white">{{ item.text }}</v-chip>
</template>
</BaseSelect>
BaseSelect component
<template>
<v-select
hide-details
solo
dense
:append-icon="mdiMenuDown"
:items="items"
v-bind="$attrs"
v-on="$listeners"
>
<!-- Passes scopedSlots to child -->
<template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope">
<slot :name="slot" v-bind="scope" />
</template>
<!-- Default scopedSlots -->
<template v-if="!hasScopedSlot('selection')" v-slot:selection="{ item }">
<span
:class="slotClasses"
>{{ item.text || $t(`select-${localKey}-option-${item.value || item}`) || item }}</span>
</template>
<template v-if="!hasScopedSlot('item')" v-slot:item="{ item }">
<span
:class="slotClasses"
>{{ item.text || $t(`select-${localKey}-option-${item.value || item}`) || item }}</span>
</template>
</v-select>
</template>

v-if="this.canupdate == true" not working

In vue I have a property this.canupdate.
My code looks like
<template v-if="this.canupdate == true">
<template v-if="row.item.edit">
<b-button variant="success" size="sm" #click="saveprestatierij(row.item, row.index)">
<i class="fas fa-save"></i>
</b-button>
</template>
<template v-else>
<b-button variant="primary" size="sm" #click="toggleeditprestatierij(row.item)">
<i class="fas fa-edit"></i>
</b-button>
</template>
</template>
But when I run the code, the block is not displaying, even if this.canupdate has a true value.
Anybody who sees where I'm wrong?
Kind regards,
Tim
Remove this from if-statement:
<template v-if="canupdate === true">
Or you can write like this:
<template v-if="canupdate">

How to use custom template for label in selected option in v-select?

I have used <template slot="option" slot-scope="option"> for custom label in v-select. Here, everything is working fine. The custom label is working fine when the options are opened as shown in the screenshot here: http://prntscr.com/kluu7p but the custom label is not working for selected option or when the select is closed: http://prntscr.com/kluudy .
Here is the snippet I have used to use custom template in v-select:
<v-select #input="updateShippingCharge"
v-model="selected"
:options="options">
<template slot="option" slot-scope="option">
<span :class="['flag-icon', `flag icon-${option.value.toLowerCase()}`]"></span>
{{ option.label }}
</template>
</v-select>
Add another template with attribute slot="selected-option".
<template slot="selected-option" slot-scope="option"></template>
The final code should look like this:
<v-select #input="updateShippingCharge"
v-model="selected"
:options="options">
<template slot="option" slot-scope="option">
<span :class="['flag-icon', `flag icon-${option.value.toLowerCase()}`]"></span>
{{ option.label }}
</template>
<template slot="selected-option" slot-scope="option">
<span :class="['flag-icon', `flag icon-${option.value.toLowerCase()}`]"></span>
{{ option.label }}
</template>
</v-select>