Delete/Edit record in vuejs - vue.js

I am using vuejsbootrap's .
I want to edit or delete single record at a time.
<b-table :items="products" :fields="fields">
<template slot="actions" slot-scope="row">
<a #click='editRecord()'><font-awesome-icon icon="edit" /></a> |
<a #click='deleteRecord()'><font-awesome-icon icon="trash-alt"
/></a>
</template>
</b-table>
i am calling editRecord and deleteRecord but i am unable to pass current record object or id to method.

Use the row variable from the slot scope:
<template slot="actions" slot-scope="row">
<a #click='editRecord(row)'><font-awesome-icon icon="edit" /></a> |
<a #click='deleteRecord(row)'><font-awesome-icon icon="trash-alt"/></a>
</template>

Related

How do i add action column with 'edit' and 'delete' buttons?

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

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.

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">

Pass scoped slots in recursive component in Vue

I want to implement vue component - tree. Each node doesn't know how to display itself, customer should know (see line 5). I want to setup scoped slots for parent node and for all children. But children data is not passed up to be displayed correctly from 3-rd level. Example https://codepen.io/vlapenkov/pen/gOpbxRG?editors=1011
<div id="app" class="jstree jstree-default jstree-default-medium">
<ul class="jstree-container-ul jstree-children jstree-no-icons">
<tree-item
v-for="(child, index) in treeData"
:item="child"
:is-last="treeData.length-1 === index"
:level="0"
>
<template scope="shape">
<div style="position:relative; display:inline-block;">{{ shape.name }}</div>
</template>
</tree-item>
</ul>
</div>
<template id="item-template" >
<li class="jstree-node" v-bind:class="className">
<i class="jstree-icon jstree-ocl" v-on:click="toggle"></i>
<a class="jstree-anchor" href="#" v-bind:class=" isSelected ? 'jstree-clicked':''">
<i class="jstree-icon jstree-themeicon"></i>
<span>{{item.name}}</span>
<slot v-bind="item"></slot>
</a>
<ul v-show="isOpen" class="jstree-children">
<tree-item
v-for="(child, index) in item.children"
:key="index"
:item="child"
:is-last="item.children.length-1 === index"
:level="level+1"
>
<slot v-bind="child"></slot>
</tree-item>
</ul>
</li>
</template>
You can pass through scoped slots like this:
<template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope"><slot :name="slot" v-bind="scope"/></template>