VueJS disable sorting when user enters data - vue.js

I have data list which I have bind to input elements in table. When table header are clicked the data list is sorted in asc or desc. Now the problem is e.g.: when user has sort "Name" column in desc and he wants to change first row name to "Dave" from "Jet Li" as soon as he type "D" the list get sorts. What can I implement to have the sorting wait for the user to type and once he finishes he can then again click the headers and sort the data.
Issue gif : Check issue here
My fiddler example : https://jsfiddle.net/bngp6oas/1/
filteredData: function () {
var sortKey = this.sortKey
var filterKey = this.filterKey && this.filterKey.toLowerCase()
var order = this.sortOrders[sortKey] || 1
var data = this.data
if (filterKey) {
data = data.filter(function (row) {
return Object.keys(row).some(function (key) {
return String(row[key]).toLowerCase().indexOf(filterKey) > -1
})
})
}
if (sortKey) {
data = data.slice().sort(function (a, b) {
a = a[sortKey]
b = b[sortKey]
return (a === b ? 0 : a > b ? 1 : -1) * order
})
}
return data
}
}

You could use the .lazy model modifier to only update the value (and therefore the sorting) after the input looses focus.
In your code from the fiddle that would look like:
<input type="text" v-model.lazy="entry[key]" />
See the Vue documentation here: https://v2.vuejs.org/v2/guide/forms.html#lazy

You can make use of the .lazy modifier.
In order to work properly, you will also need to add a unique key to each row.
Updated grid data with keys:
gridData: [
{ id: 1234 , name: 'Chuck Norris', power: Infinity },
{ id: 2345, name: 'Bruce Lee', power: 9000 },
{ id: 3456, name: 'Jackie Chan', power: 7000 },
{ id: 4567, name: 'Jet Li', power: 8000 }
]
See updated fiddle here

Related

Prepopulate the text box for dataTables individual column searching

this should be easy but all the examples I can find are specific to the "general search" text box.
I'm trying to prepopulate an individual column search box, for example the "Name" field.
I don't need the code to do the search, just code to put a value in that "Search Name" text field.
There are 2 steps you can take to achieve this.
Step 1:
Use the searchCols option to set up your initial search terms. For example:
"searchCols": [
{ "search": "sat" }
]
This will cause column 1 to be filtered on the string sat.
If you want to use additional or different column filters, you can use null to skip columns - for example:
"searchCols": [
null,
{ "search": "foo" }
null,
{ "search": "bar" }
]
The above example will filter the 2nd and 4th columns.
Step 2:
You can take the existing code which creates the input fields in the table's footer cells, and modify that code to (a) use an index, and then (b) use the index to target the specific column(s) you want to pre-populate:
$('#example tfoot th').each(function ( idx ) {
var title = $(this).text();
$(this).html('<input type="text" placeholder="Search ' + title + '" />');
if ( idx === 0 ) {
$(this).find( 'input' ).val( 'sat' );
}
});
In the above fragment, I took the code linked to in the question and added the idx variable, and then used that to target the first input field, and populate it with "sat".
Without step 2, the DataTable will not show you the values being used to perform filtering.
initComplete: function () {
this.api().columns().every( function () {
var column = this;
if ($(column.header()).hasClass('datatable_search')) {
var that = this;
//player var taken from url
if (column.header().innerText.includes('Players') && players.length){
//prepopulate the input field
$( 'input', this.header() ).val(players)
//use the url.players arg in the search and redraw
this.search( players ).draw();
}
$( 'input', this.header() ).on( 'keyup change clear', function () {
if ( that.search() !== this.value ) {
that
.search( this.value )
.draw();
}
} );

How to not trigger watch when data is modified on specific cases

I'm having a case where I do wish to trigger the watch event on a vue project I'm having, basically I pull all the data that I need then assign it to a variable called content
content: []
its a array that can have multiple records (each record indentifies a row in the db)
Example:
content: [
{ id: 0, name: "First", data: "{jsondata}" },
{ id: 1, name: "Second", data: "{jsondata}" },
{ id: 2, name: "Third", data: "{jsondata}" },
]
then I have a variable that I set to "select" any of these records:
selectedId
and I have a computed property that gives me the current object:
selectedItem: function () {
var component = this;
if(this.content != null && this.content.length > 0 && this.selectedId!= null){
let item = this.content.find(x => x.id === this.selectedPlotBoardId);
return item;
}
}
using this returned object I'm able to render what I want on the DOM depending on the id I select,then I watch this "content":
watch: {
content: {
handler(n, o) {
if(o.length != 0){
savetodbselectedobject();
}
},
deep: true
}
}
this work excellent when I modify the really deep JSON these records have individually, the problem I have is that I have a different upload methord to for example, update the name of any root record
Example: changing "First" to "1"
this sadly triggers a change on the watcher and I'm generating a extra request that isnt updating anything, is there a way to stop that?
This Page can help you.
you need to a method for disables the watchers within its callback.

dynamically add new fields to b-table [ Vue.js ]

I am trying to create a table using bootstrap table with fields dynamically added. The fields that will be added will be taken from my api (see code below).
vue.js (jade) - The 2nd template will be the one to render the dynamically added fields but the problem is I can't access the row.item.members because I am not in the row scope. If there is a way to access the row data in the template tag it would be great but I already spent a day and found no luck
b-table(small v-bind:items="plans" v-bind:fields="fields" fixed responsive)
template(slot='bg_action', slot-scope='row')
nuxt-link(:to="'/supply_and_demand/master/'+selected+'/'+row.item.date")
b-button.mr-1(size='sm', variant="primary")
| {{ row.item.date }}
template(v-for="member_info in row.item.members" :slot="id_+ 'member_info.id'" )
| {{ member_info.name }}
my api call (which adds new fields to the table and get the data)
async fetchData(){
let params = {
"q[balancing_group_id_eq]": this.selected
}
this.$restApi.index('bg_members', {params})
.then( (result)=>{
this.fields = [
{ key: 'date', label: '' },
{ key: 'bg_action', label: 'BG' }
]
for(let i = 1; i <= result.length; i++){
this.fields.push({ key: 'id_' + result[i-1].company.id, label: result[i-1].company.name })
}
})
params = {
"q[balancing_group_id_eq]": this.selected,
"q[date_gteq]": this.from,
"q[date_lteq]": this.to
}
this.$axios.$get('/v1/occto/plans', { params })
.then( (result)=>{
console.log("plans")
console.log(this.plans)
this.plans = result
})
}
tldr:I want to access the row data inside the template tag so I can dynamically set the slot which will result to data being displayed properly.

How to get filtered rows from GridX?

I'm using Dojo GridX with many modules, including filter:
grid = new Grid({
cacheClass : Cache,
structure: structure,
store: store,
modules : [ Sort, ColumnResizer, Pagination, PaginationBar, CellWidget, GridEdit,
Filter, FilterBar, QuickFilter, HiddenColumns, HScroller ],
autoHeight : true, autoWidth: false,
paginationBarSizes: [25, 50, 100],
paginationBarPosition: 'top,bottom',
}, gridNode);
grid.filterBar.applyFilter({type: 'all', conditions: [
{colId: 'type', condition: 'equal', type: 'Text', value: 'car'}
]})
I've wanted to access the items, that are matching the filter that was set. I've travelled through grid property in DOM explorer, I've found many store references in many modules, but all of them contained all items.
Is it possible to find out what items are visible in grid because they are matching filter, or at least those that are visible on current page? If so, how to do that?
My solution is:
try {
var filterData = [];
var ids = grid.model._exts.clientFilter._ids;
for ( var i = 0; i < ids.length; ++i) {
var id = ids[i];
var item = grid.model.store.get(id);
filterData.push(item);
}
var store = new MemoryStore({
data : filterData
});
} catch (error) {
console.log("Filter is not set.");
}
I was able to obtain filtered gridX data rows using gridX Exporter. Add this Exporter module to your grid. This module does exports the filtered data. Then, convert CSV to Json. There are many CSV to Json conversion javasripts out there.
this.navResult.grid.exporter.toCSV(args).then(this.showResult, this.onError, null)
Based on AirG answer I have designed the following solution. Take into account that there are two cases, with or without filter and that you must be aware of the order of rows if you have applied some sort. At least this works for me.
var store = new Store({
idProperty: "idPeople", data: [
{ idPeople: 1, name: 'John', score: 130, city: 'New York', birthday: '31/02/1980' },
{ idPeople: 2, name: 'Alice', score: 123, city: 'WÃĄshington', birthday: '07/12/1984' },
{ idPeople: 3, name: 'Lee', score: 149, city: 'Shanghai', birthday: '8/10/1986' },
...
]
});
gridx = new GridX({
id: 'mygridx',
cacheClass: Cache,
store: store,
...
modules: [
...
{
moduleClass: Dod,
defaultShow: false,
useAnimation: true,
showExpando: true,
detailProvider: gridXDetailProvider
},
...
],
...
}, 'gridNode');
function gridXDetailProvider (grid, rowId, detailNode, rendered) {
gridXGetDetailContent(grid, rowId, detailNode);
rendered.callback();
return rendered;
}
function gridXGetDetailContent(grid, rowId, detailNode) {
if (grid.model._exts.clientFilter._ids === undefined || grid.model._exts.clientFilter._ids === 0) {
// No filter, with or without sort
detailNode.innerHTML = 'Hello ' + grid.row(grid.model._cache._priority.indexOf(rowId)).item().name + " with id " +
grid.row(grid.model._cache._priority.indexOf(rowId)).item().idPeople;
} else {
// With filter, with or without sort
detailNode.innerHTML = 'Hello ' + grid.row(grid.model._exts.clientFilter._ids.indexOf(rowId)).item().name + " with id " +
grid.row(grid.model._exts.clientFilter._ids.indexOf(rowId)).item().idPeople;
}
}
Hope that helps,
Santiago Horcajo
function getFilteredData() {
var filteredIds = grid.model._exts.clientFilter._ids;
return grid.store.data.filter(function(item) {
return filteredIds.indexOf(item.id) > -1;
});
}

Store filter in sencha touch

I have store having structure :
Ext.create('Ext.data.Store', {
fields: [
'title'
],
data: [{
title: 'ABC'
}, {
title: 'ABC2'
}, {
title: 'ABC3'
}, {
title: 'ABC4'
}, {
title: 'ABC5'
}, {
title: 'ABC6'
}]
});
So when I load this store List get populated with all 6 records.
I just wanted to Filter this store on button click I just wanted to get some selected record out of this 6 record Can It be possible.
Provide me Some Idea or Working code.
To filter the store based on title
Ext.getStore('storeId').filter("title", "ABC3");
To clear filter
Ext.getStore('storeId').clearFilter();
See store filter doc
Update
Ext.getStore('storeId').filterBy(function(record){
var title = record.get('title');
if(title == "ABC" || title == "ABC1" || title == "ABC2")
return record;
});
My approach is to set a filter on the store when I tap on the button. In my case it was a selectfield and on the change event I filter compared to the current value in the selectfield
onChangeStatusSelectfield: function (newValue, oldValue) {
var store = Ext.getStore('CustomVacationRequest');
console.log('Accepted Filter');
newValue = this.getStatusSelectfield().getValue();
console.log(store, newValue);
store.clearFilter();
if (store != null);
store.filter(function (record) {
if (newValue == record.data.status) { //your data from the store compared to
//the value from the selectfield
return true;
}
Ext.getCmp("VacationRequestsManagerList").refresh() //refresh your list
});
},
This is just my part of the controller. Handle events and buttons and stores at your own choice&need. Good luck!