Bootstrap -vue table how to remove row with animation - javascript

I'm using bootstrap vue tables, and I'd like to remove rows with animation.
When attaching animation to the table, the removed row doesn't animate, but the rows that move up to fill its place do animate. How do I make the removed row animate as well?
I've tried dozens of animation classes and property values in the css, but none of them seem to have any effect on the row being removed.
(please note that the snippet is cut off at the bottom, so to demo the remove button press, view the snippet in full screen)
Vue.config.productionTip = false;
var app = new Vue({
el: '#app',
methods: {
clickedRemove() {
this.items = this.items.filter(i => i.first_name !== 'Larsen');
}
},
data: {
transProps: {
name: 'v'
},
fields: [{
key: 'first_name',
label: 'Given Name'
},
{
key: 'age',
label: 'How Old'
},
{
key: 'last_name',
label: 'Surname'
},
],
items: [{
age: 40,
first_name: 'Dickerson',
last_name: 'Macdonald'
},
{
age: 21,
first_name: 'Larsen',
last_name: 'ANIMATE THIS ON REMOVE ??'
},
{
age: 89,
first_name: 'Geneva',
last_name: 'Wilson'
},
]
}
})
table#table-transition-example .v-enter-active, .v-leave-active {
transition: opacity 0.5s ease;
}
table#table-transition-example .v-enter-from, .v-leave-to {
opacity: 0;
}
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.1/bootstrap-vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
<div id="app">
<div>
<b-table striped small :items="items" :fields="fields"
id="table-transition-example" class="fade-out"
:tbody-transition-props="transProps"
>
<template #cell(age)="{ item }">
<p class="text-info">age {{ item.age }}</p>
</template>
</b-table>
<b-button #click="clickedRemove">Remove Larsen With Animation</b-button>
</div>
</div>

Related

Filter BootstrapVue table using comma separated string with OR condition in input field

I have a BootstrapVue table that looks like this;
The code(credit goes to this answer) for the table is here;
new Vue({
el: '#app',
data() {
return {
filter: '',
items: [
{ id: 1, first_name: "Mikkel", last_name: "Hansen", age: 54 },
{ id: 2, first_name: "Kasper", last_name: "Hvidt", age: 42 },
{ id: 3, first_name: "Lasse", last_name: "Boesen", age: 39 },
{ id: 4, first_name: "Kasper", last_name: "Hansen", age: 62 },
{ id: 5, first_name: "Mads", last_name: "Mikkelsen", age: 31 },
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.6.1/dist/bootstrap-vue.min.js"></script>
<link href="https://unpkg.com/bootstrap-vue#2.6.1/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css" rel="stylesheet" />
<div id="app" class="p-5">
<b-input v-model="filter" placeholder="Filter table.."></b-input>
<hr />
<b-table :items="items" :fields="fields" :filter="filter">
</b-table>
</div>
Based on the above code, table rows will be filtered based on the string inside the input field. Unfortunately, this is not what I want. What I want is for the input field to be able to accept a comma-separated string and the sub-strings can be used to filter the table rows in an OR condition. For example, if the string is 54, Hvidt, then the first and second rows will be filtered.
I am using BootstrapVue, vue.js 2.6
BootstrapVue allows writing your own logic for filtering, using a custom filter function.
In order for it to work, you need:
a :filter specified
the filter value to be truthy. If it's falsey, the filter function is bypassed (no filtering occurs).
a :filter-function specified, taking two arguments: row and current filter value (optional and not needed: you can read it from this.filter).
Here's an example, splitting current filter value by , (comma), normalising the fragments (trim & toLowerCase), and returning whether or not any fragment is found within the normalised values of the row.
new Vue({
el: '#app',
data() {
return {
filter: '54, Hvidt',
items: [
{ id: 1, first_name: "Mikkel", last_name: "Hansen", age: 54 },
{ id: 2, first_name: "Kasper", last_name: "Hvidt", age: 42 },
{ id: 3, first_name: "Lasse", last_name: "Boesen", age: 39 },
{ id: 4, first_name: "Kasper", last_name: "Hansen", age: 62 },
{ id: 5, first_name: "Mads", last_name: "Mikkelsen", age: 31 }
]
}
},
methods: {
normalizeString(s) {
return `${s}`.trim().toLowerCase();
},
filterFn(row) {
return this.filter.split(',')
.map(this.normalizeString)
.some(
term => Object.values(row)
.map(this.normalizeString)
.some(
val => val.indexOf(term) > -1
)
);
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.14"></script>
<script src="https://unpkg.com/bootstrap-vue#2.6.1/dist/bootstrap-vue.min.js"></script>
<link href="https://unpkg.com/bootstrap-vue#2.6.1/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css" rel="stylesheet" />
<div id="app" class="p-5">
<b-input v-model="filter" placeholder="Filter table..."></b-input>
<hr />
<b-table :items="items" :filter="filter" :filter-function="filterFn">
</b-table>
</div>
Important note: the filter function provided here is demonstrative, it doesn't take into account BootstrapVue's built-in filter-ignored-fields and filter-included-fields. Nor does it take into account the filterByFormatted field definition.
If you need any of those features, you'll need to improve it yourself.
I guess it's needless to point out the filter function has access to the entire component and can be modified in any way. The row is displayed if the function returns a truthy value and is not displayed if it returns a falsey value.

How to give a link to each row in bootstrap-vue table

I have an bootstrap-vue table in my project.
I want to give each row a link (something like code below)
<template #row>
<div #click="goToPage">
{{ item.name}}
</div>
</template>
but do not know how to access table tr in bootstrap
codesandbox
i would really appreaciate if someone can help me with it
You can add selectable to your table and event row-selected:
<b-table select-mode="single" ref="selectableTable" selectable #row-selected="onRowSelected" small :fields="fields" :items="items" responsive="sm">
and then create method:
methods: {
onRowSelected(item) {
console.log(item)
}
}
You can use the #row-clicked event, which as the name suggests is triggered when a row is clicked.
The method is sent the item for the row which was clicked, so you can access any information from the item if needed. Along with the index and native click event.
new Vue({
el:"#app",
data: () => ({
items: [
{ age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
{ age: 11, first_name: 'Larsen', last_name: 'Shaw' },
{ age: 89, first_name: 'Geneva', last_name: 'Wilson' },
{ age: 38, first_name: 'Jami', last_name: 'Carney' }
]
}),
methods: {
onRowClicked(item, index, event) {
console.log(item)
}
}
});
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.js"></script>
<div id="app" class="p-3">
<b-table striped hover :items="items" #row-clicked="onRowClicked"></b-table>
</div>

dynamic vuetify breadcrumbs list items

I want to use breadcrumbs in my vuetify project but I'm stuck somewhere. The point I'm stuck with is that when I click on bredcrumbs, the ones that come after that are deleted from the breadcrumbs list. For this, I tried the code below, but I could only delete the next element from it. Also, I couldn't delete the dividers. How do you think I can overcome this situation? thanks.
template:
<v-breadcrumbs :items="items" divider=">">
<template v-slot:item="{ item }">
<v-breadcrumbs-item :href="item.href" #click="showSelectedRow2(item)">
{{ item.text }}
</v-breadcrumbs-item>
</template>
</v-breadcrumbs>
Data:
items: [
{
text: '',
disabled: false,
id: '',
},
],
Script:
showSelectedRow2(item) {
for (var i = 0; i < this.items.length; i++) {
if (this.items[i].id == item.id) {
const index = this.items.indexOf(this.items[i]);
this.items.splice(index, 1);
}
this.items.push({
text: item.name,
disabled: false,
id: item.id,
});
}
},
eg Technology>Computer>laptop>Apple when I click on technology, only technology should remain in the list. I don't use route or link, I fill the list with data I get from an api.
You can try to change your method like in the following snippet:
(you can disable items or you can remove them)
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
items: [{text: 'Technology', disabled: false, id: 0,}, {text: 'Computer', disabled: false, id: 1,}, {text: 'Laptop', disabled: false, id: 2,}, {text: 'Apple', disabled: false, id: 3,},],
}
},
methods: {
itemIdx(itm) {
return this.items.findIndex(i => i.id === itm.id)
},
showSelectedRow2(item) {
//this.items = this.items.map(el => this.itemIdx(el) > this.itemIdx(item) ? {...el, disabled: true} : el)
this.items = this.items.filter(el => this.itemIdx(el) <= this.itemIdx(item))
}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
<v-breadcrumbs :items="items" divider=">">
<template v-slot:item="{ item }">
<v-breadcrumbs-item :href="item.href" #click="showSelectedRow2(item)">
{{ item.text }}
</v-breadcrumbs-item>
</template>
</v-breadcrumbs>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

Live filter in custom select with input

I am trying to make a custom list filter on input using computed property. In one file I create a widget, in another I use it. Here is the code from the widget creation file:
<template>
<input value="Гарантийный случай"
v-model="searchText"
:class="{'w-autocomplete__input_completed': completed}"
ref="input"
#click="areOptionsVisible = !areOptionsVisible"/>
<div v-if="areOptionsVisible"
:style="{maxHeight: maxHeight, overflow: 'auto', zIndex: zIndex}"
class="w-autocomplete__items">
<div v-for="option in options" class="w-autocomplete__item_first" >
{{ option.name }}
<div v-for="item in option.children" class="w-autocomplete__item"
:class="{'w-autocomplete__item_active': currentIndex === item}"
#mouseenter="setActive(item)"
#keyup.up="changeCurrent('up', item)"
#keyup.down="changeCurrent('down', item)"
#click="doChoose(item)">
{{ item.name }}
</div>
</div>
</div>
</template>
<script>
export default {
name: 'dropdown',
props: {
placeholder: {
type: String,
required: false,
default: '',
},
options: {
type: Array,
default(){
return []
}
},
},
data: function () {
return {
counter: 0,
currentIndex: null,
completed: false,
chosenItem: null,
areOptionsVisible: false,
searchText: '',
data: [],
}
},
computed: {
options(){
return this.props.options.filter(elem => {
return elem.name.toLowerCase().includes(this.searchText.toLowerCase());
});
},
},
.......
}
</script>
This is how I pass the array to this list in another file:
<template>
........
<div class="complaint-form__line-item">
<div class="form-group">
<label>Гарантийный случай</label>
<dropdown :options="options" />
</div>
</div>
........
</template>
<script>
........
export default {
name: 'complaint-form',
components: {LockedImport, UploadFiles, CarNumberInput, Autocomplete, Dropdown},
props: {
......
}
},
data() {
const complaint = new Complaint();
return {
........
options: [
{name: 'Выход детали из строя в процессе эксплуатации', value: null,
children: [{name: 'Увеличение зазора, люфт (дробь/стуки)', value: 53},
{name: 'Обрыв детали', value: 54}]},
{name: 'Поломка при установке', value: null},
{name: 'Брак до установки', value: null,
children: [{name: 'Недокомплект', value: 55},
{name: 'Заводской брак (замятия, отсутствие резьбы, пробой пыльника и т.д.)',
value: 56}]},
],
}
},
Tell me please why computed doesn't work? Only I add computed and the list is not displayed at all when clicking on the field, but should. That is, it breaks down completely. I want to be filtered when entering text in input
Vue.js cannot have more than one element inside a <template> tag, so I would suggest that you enclose the whole code of the dropdown component within a <div> tag or something of the sort.
Also, and this is just a comment, I would suggest that you use the focus event for the input because with click it will still be showing even if you aren't focusing on the input.

How to use <b-pagination-nav> from Bootstrap Vue?

I want to start using the introduced in this tutorial. The problem is that that I don't know how to make the tag to work on my website. The explanation that is given in the tutorial on how to do that is very vague and as a beginner, I can't make it work.
I installed bootstrap and bootstrap-vue and added the .css and .js files the following way:
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap-vue.min.css">
<script src="js/bootstrap-vue.min.js"></script>
However, I don't think any of these add the tag, because when I try to implement it, it is not appearing. At the bottom of the tutorial linked above, there is a section that gives information on how to import single elements. I tried to use the lines of code provided there but it did not change anything. Please, help me.
On BootstrapVue website you will find everything you need in order to use it.
Your case is listed under #Browser section of Getting Started. Make sure you add all those dependencies to your page's <head>.
And, as for using it, you have to initialize a Vue instance on window.load event, at the earliest.
Example:
window.onload = () => {
new Vue({
el: '#app',
data() {
return {
perPage: 3,
currentPage: 1,
items: [
{ id: 1, first_name: 'Fred', last_name: 'Flintstone' },
{ id: 2, first_name: 'Wilma', last_name: 'Flintstone' },
{ id: 3, first_name: 'Barney', last_name: 'Rubble' },
{ id: 4, first_name: 'Betty', last_name: 'Rubble' },
{ id: 5, first_name: 'Pebbles', last_name: 'Flintstone' },
{ id: 6, first_name: 'Bamm Bamm', last_name: 'Rubble' },
{ id: 7, first_name: 'The Great', last_name: 'Gazzoo' },
{ id: 8, first_name: 'Rockhead', last_name: 'Slate' },
{ id: 9, first_name: 'Pearl', last_name: 'Slaghoople' }
]
}
},
computed: {
rows() {
return this.items.length
}
}
})
}
<!-- Add this to <head> -->
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<!-- Load polyfills to support older browsers -->
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<!-- Example #app template -->
<div id="app">
<template>
<div class="overflow-auto">
<b-pagination
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
aria-controls="my-table"
></b-pagination>
<p class="mt-3">Current Page: {{ currentPage }}</p>
<b-table
id="my-table"
:items="items"
:per-page="perPage"
:current-page="currentPage"
small
></b-table>
</div>
</template>
</div>

Categories