bootstrap table not refreshing switch properly - vue.js

I created two tables, one displays all items where the property "selected" is false and the other is "true"
To toggle between the two tables, I've used a dev extreme switch.
When a user switches from false to true (or on to off), the element will refresh and render properly on the correct table, however the switch seems to be stuck.
Example:
Initial Table
Table of False Elements
a - switch shows false
b - switch shows false
c - switch shows false
Table of True Elements
d - switch shows true
e - switch shows true
If a user clicks "a" in the first table, the following is what will be rendered
Table of False Elements
b - switch shows true
c - switch shows false
Table of True Elements
a - switch shows true
d - switch shows true
e - switch shows true
Furthermore, these tables have pagination, navigating between pages, the row in which the element was clicked will remain "true" from page to page.
<b-table :fields="fields" :items="UnselectedAccounts" striped ref="UnselectedTable" :per-page="perPage" :current-page="currentPage">
<template slot="Selected" slot-scope="row">
<dx-switch type="checkbox" v-model:value="row.item.Selected" #value-changed="switchChange()"></dx-switch>
</template>
</b-table>
<b-table :fields="fields" :items="SelectedAccounts" striped ref="SelectedTable">
<template slot="Selected" slot-scope="row">
<dx-switch type="checkbox" v-model="row.item.Selected" #value-changed="switchChange()"></dx-switch>
</template>
</b-table>
My switch change method (I have tried creating the variables as computed but results are the same)
switchChange() {
if (!this.EnterpriseData.AssociatedAccounts) {
this.UnselectedAccounts = [...this.UnassignedAccounts].filter(r => r.Selected === false)
this.SelectedAccounts = [...this.UnassignedAccounts].filter(r => r.Selected === true)
} else {
this.UnselectedAccounts = [...this.UnassignedAccounts, ...this.EnterpriseData.AssociatedAccounts].filter(r => r.Selected === false)
this.SelectedAccounts = [...this.UnassignedAccounts, ...this.EnterpriseData.AssociatedAccounts].filter(r => r.Selected === true)
}

Related

I want to add active class on the button that got clicked and remove from the another button, vice versa in vue js

I want to add an active class while the first button is clicked and remove the active class if it's there in the second button same condition for the second button how can I achieve it.
<button
:class="{ active: isActiveAc, sortas: true }"
#click="sortUp()"
>
Price low to Hight
</button>
<button
:class="{ active: isActiveDc, sortas: true }"
#click="sortDown()"
>
Price Hight to Low
</button>
I would like to give you a basic idea which might help you.
<button :class="{ active: isActiveAc, sortas: true }"#click="sortUp(),setFalse(1)>Price low to Hight</button>
<button:class="{ active: isActiveDc, sortas: true }"#click="sortDown(),setFalse(1)">Price Hight to Low</button>
and add the following function in a method.
setFalse(c) {
if (c == 1) {
this.isActiveAc = true;
this.isActiveDc = !this.isActiveAc;
} else if (c == 2) {
this.isActiveDc = true;
this.isActiveAc = !this.isActiveDc;
}
},

Vuetify: How to show overlay with spinner while v-data-table renders (how to wait for a component to finish rendering)

I have a Vuetify v-data-table with about a 1000 rows in it. Rendering it for the first time and when text searching on it, the render takes a few seconds. During this time I want to overlay it with a scrim + spinner to indicate things are happening.
The overlay:
<v-overlay
:value="loading"
opacity="0.7"
absolute
v-mutate="onMutate"
>
<v-progress-circular indeterminate size="32" color="blue"></v-progress-circular>
</v-overlay>
The v-data-table:
<v-data-table
:headers="cHeaders"
:items="cLimitedData"
disable-pagination
hide-default-footer
:search="searchIntercepted"
#current-items="tstCurrentItems"
>
The computed variable cLimitedData:
cLimitedData() {
if (this.indNoLimit) {
return this.data
} else {
return this.data.slice(0,this.dtRowTo)
}
},
I watch the search variable, and when it changes, I set loading to true to activate the overlay.
watch: {
search() {
if (!this.indNoLimit) {
// remove limit, this will cause cLimitedData to return all rows
this.loading = true
// -> moved to onMutate
//this.$nextTick(function () {
// this.indNoLimit = true
//})
} else {
this.searchIntercepted = this.search
}
},
However, the overlay doesn't activate until after the v-data-table had finished rendering. I've tried a million things, one of them is to put a v-mutate="onMutate" on the overlay, and only when it fired, would I this.indNoLimit = true to set things in motion, but that is still not good enough to have the scrim start before the v-data-table begins reloading itself.
onMutate(thing1) {
console.log('#onMutate',thing1)
this.$nextTick(function () {
this.indNoLimit = true
this.searchIntercepted = this.search
})
},
I also found that the next tick in #current-items fairly reliably marked the end of the render of the v-data-table, thus the deactivation of the scrim is probably going to be ok:
tstCurrentItems(thing1) {
console.log('#current-items',thing1)
this.$nextTick(function () {
console.log('#current-items NEXT')
this.loading = false
})
I believe my question should be: how can I detect/wait for components to have rendered (the v-overlay+v-progress-circular) before making changes to other components (the v-data-table).
Note: To solve the initial wait time of loading of the table, I found a way to progressively load it by inserting div-markers that trigger a v-intersect. However, this does not solve the situation when a user searches the whole data set when only the first 50 rows are loaded.
EDIT: Tried to start the update of the table after the overlay has been activated using https://github.com/twickstrom/vue-force-next-tick, but still no luck. It almost looks like vue tries to aggregate changes to the DOM instead of executing them one by one.
I have not figured out why the v-data-table seems to block/freeze, but here is a solution that can streamline any large v-data-table:
The v-data-table:
<v-data-table
:headers="cHeaders"
:items="data"
:items-per-page="dtRowTo"
hide-default-footer
hide-default-header
:search="search"
item-key="id"
>
<template
v-slot:item="{item, index, isSelected, select, headers}"
>
<tr>
<td
:colspan="headers.length"
>
Stuff
<div v-if="(index+1)%25==0" v-intersect.quiet.once="onIntersect">{{index+1}}</div>
</td>
</tr>
</template>
</v-data-table>
Add a div, or any other element, to intersect with at given intervals. Every time we intersect with it, we're going to increase the page size.
Variables:
dtRowTo: 50, // initial nr of rows
dtRowIncr: 50, // increments
The onIntersect:
onIntersect (entries, observer) {
let index = entries[0].target.textContent
if (index == this.dtRowTo) {
this.dtRowTo += this.dtRowIncr
}
},
Unfortunately you cannot add the index as an argument like v-intersect.quiet.once="onIntersect(index)", as this executes the function before you intersect with it (not sure why), so we will have to take the index out of the textContext.
Basically what you do is you increase the page size every time you're at the bottom. Search will still operate on the whole dataset.
What does not work (which I found out the hard way), is incrementally increasing the items, like the computed function below. As search needs the entire dataset to be present at :items, this won't work:
<v-data-table
:items="cLimitedData"
computed: {
cLimitedData() {
return this.data.slice(0,this.dtRowTo)
},
}
Doing so is fine (I guess?) as long as you don't need search or anything that operates on the entire data set.

Vuetify combobox - How to disable typing in vuetify's combobox

The vuetify combobox is allowing the user to type inside the combobox. Any clue on how to disable this.
This is how I have implemented my combobox.
<v-combobox
:loading="isSurveyBeingPopulated"
class="static--inputs"
color="red"
box
:items="folders"
:rules="[rules.required]"
item-text="value"
dense
placeholder="Select Survey Folder"
item-value="key"
slot="input"
v-model="selectedSurveyFolder">
</v-combobox>
Combobox:
The v-combobox component is a v-autocomplete that allows the user to
enter values that do not exist within the provided items. Created
items will be returned as strings.
So if you want to disable the typing you should use a select: https://vuetifyjs.com/en/components/selects
Select fields components are used for collecting user provided
information from a list of options.
You can just delete new item after changed.
<v-combobox
v-model="selected"
:items="[...selected, ...items]"
multiple
#change="onChangeCombobox"
/>
onChangeCombobox(items) {
this.selected = items.filter((item) => this.items.includes(item))
}
I had the same problem, I used v-select instead of v-combobox, it works fine:
<v-select
return-object
></v-select>
I've gone thru the same, i need combobox to list item and custom values but i must disable typing, my solutions was to use key events and "change"its behavior like:
#keydown="$event.target.blur()"
#keypress="$event.target.blur()"
#keyup="$event.target.blur()"
Yes, you can achieve filtering of a combobox by using the rules code, e.g.
<v-combobox
v-model="selection"
:items="items"
:search-input.sync="input"
:rules="intRule"
chips
clearable
dense
multiple
small-chips
item-text="title"
autocomplete="off"
return-object
>
</v-combobox>
and then in your script section in data, sth like
data() {
return {
selection: [],
input: null,
items: [],
valid: false,
intRule: [
function(v) {
if (!v || v.length < 0) {
return false
} else if (v.length > 0) {
for (let i = 0; i < v.length; i++) {
if (/[^0-9]/g.test(v[i].id)) {
v.splice(-1, 1)
return false
}
}
return false
} else {
return true
}
}
]
}
}
the input could be used to overwrite a no results slot and show for what input are no results found.
hope this is helping

Datatable vuetify select multiple rows (Shift+Click)

I am using Datatable from Vuetify 1.5.x
Have enabled the checkboxes so that multiple rows can be selected, I would like to be able to select with Shift + Click so that I don't have to click on each checkbox exact same as Gmail works.
It wouldn't be difficult to do if I had a row id that changes by the sort or if the rows array was reordered when the data table is sorted. But none of these seem to work.
Has anyone achieve this with vuetify datatable?
<template v-slot:items="props">
<tr :active="props.selected" #click="selectRow(props);">
<td>
<v-layout>
<v-flex>
<v-checkbox
:input-value="props.selected"
primary
hide-details
:class="{ 'red--text': props.item.was_modified_recently == 1 }"
></v-checkbox>
</v-flex>
</td>
</tr>
</template>
Vuetify documentation example
I actually had to solve this today.
My solution relied on using the item-selected hook and method that performs the bulk selection.
methods: {
bulkSelect({ item: b, value }) {
const { selectedRows, current, shiftKeyOn } = this;
if (selectedRows.length == 1 && value == true && shiftKeyOn) {
const [a] = selectedRows;
let start = current.findIndex((item) => item == a);
let end = current.findIndex((item) => item == b);
if (start - end > 0) {
let temp = start;
start = end;
end = temp;
}
for (let i = start; i <= end; i++) {
selectedRows.push(current[i]);
}
}
},
}
So that's the meat of it. There's other housekeeping details like keeping track of when shift is being held down, and preventing the browser from highlighting the text of the table when holding down shift and clicking the second row.
I made a codepen showing this functioning here.
https://codepen.io/ryancwynar/pen/jOWoXZw
In the new version of vuetify i.e. 2.0
You question is solved easily the following way
I have put the answer in the following Stack Overflow question link
Vuetify added prepend-item slot that lets you add a custom item before listing items by which we can add "select all"
Please check the example in codepen on pretend-item for select all checkboxes
I've got the same case as you faced.
First of all, you got to add another events (keyboard events) on the <tr>
tag and pass the props as argument.
And then use slice to the items array for determined range of the selected items you want.
In my case, i've stored the selected array inside vuex store.
hoped i can helped ;)
<template v-slot:items="props">
<tr :active="props.selected" #click.shift="useShift(props)" #click="selectRow(props)">
<td>
<v-layout>
<v-flex>
<v-checkbox
:input-value="props.selected"
primary
hide-details
:class="{ 'red--text': props.item.was_modified_recently == 1 }"
></v-checkbox>
</v-flex>
</td>
</tr>
</template>
export default {
methods:{
...mapMutations(["setSelected"]),
useShift({ index }) {
this.setSelected(
this.items.slice(
this.items.findIndex(el => {
return this.selected.find(v => v.track.id == el.track.id);
}),
index
)
);
},
}
}

Jquery Tabs MVC 4 - Redirect to to tab from controller

I have the following code where 'SelectedTabToFind' is set in the controller. This is used for validation, so that the correct tab is displayed.
$("#tabs").tabs(
{
active: $("#SelectedTabToFind").val(),
cache: false
});
<div id="tabs">
<ul>
<li>View</li>
<li>Update</li>
<li>Validate</li>
<li>Notes</li>
</ul>
<div id="tabs-1">
#Html.Partial("View",Model)
</div>
<div id="tabs-2">
#Html.Partial("Update",Model)
</div>
<div id="tabs-3">
#Html.Partial("Validate",Model.ValidateModel)
</div>
<div id="tabs-4">
#Html.Partial("Notes", Model)
</div>
View Tab - Displays Information
Update Tab - Can update information on tab
Validate Tab - Can update information on tab
Notes Tab - Displays a list of information with separate page outwith tabs to add/update a note
The validation works and displays correctly for Update and Validate tabs. The redirect does not work when I add/update a note as it uses a separate page outwith the tabs.
I have used the following code before to redirect to a tab
return Redirect(Url.Action("View", new { id = note.Id }) + "#tabs-4");
and this does not work with the above code
If I comment out 'active' it works correctly
$("#tabs").tabs(
{
//active: $("#SelectedTabToFind").val(),
cache: false
});
How do I redirect to the correct tab but keep active option for validation?
When you redirectto a tab, that tab becomes automatically active. You cannot do something and its contrary!
From jquery tabs doc
active
Type: Boolean or Integer
Default: 0
Which panel is currently open.
Multiple types supported:
Boolean: Setting active to false will collapse all panels. This requires the collapsible option to be true.
Integer: The zero-based index of the panel that is active (open). A negative value selects panels going backward from the last panel.
With the help of JQuery UI tabs: How do I navigate directly to a tab from another page?
The correct tab is displayed when validating a form and the redirect from another page works as well.
View Page
if (document.location.hash != '')
{
var tabSelect = document.location.hash.substr(1, document.location.hash.length);
//Used to return to tab using return Redirect(Url.Action("View", new { id = note.Id }) + "#4");
$("#tabs").tabs(
{
active: tabSelect,
cache: false
});
}
else
{
$("#tabs").tabs(
{
//Used to return to tab using return ViewModel.SelectedTab = 2;
active: $("#SelectedTabToFind").val(),
cache: false
});
}
Used for note section in controller
return Redirect(Url.Action("View", new { id = note.Id}) + "#4");
Used for Update and Validate section in controller
ViewModel.SelectedTab = 2;