Filter by column in attribute table
It would be interesting to have text input above all/some columns to filter them one by one.
Here is some code to add this enhancement by extending Lizmap.
Limitation : it adds a text input on every columns with values. The filter just look for strings matching the word searched. I've put a setTimeout because of #997 .
This code can be adapted to make smarter search based on attributes type.
lizMap.events.on({
attributeLayerContentReady: function(e) {
setTimeout(function(){
$('#attribute-layer-table-'+e.featureType+'_wrapper thead:first th').not('.sorting_disabled').each( function () {
var title = $(this).text();
$(this).html( '<input type="text" placeholder="Search'+title+'" />' );
});
var table = $('#attribute-layer-table-'+e.featureType).DataTable();
table.columns().every( function () {
var column = this;
$( 'input', this.header() ).on( 'keyup change', function () {
if ( column.search() !== this.value ) {
column
.search( this.value )
.draw();
}
}).click(function(e) {
// We don't want to sort when users click on the search field
e.stopPropagation();
});
});
lizMap.refreshDatatableSize("#attribute-layer-main-"+e.featureType)
}, 10);
}
});
Thank you for this code. It's really useful.
However, this works for some layers and not others. I couldn't find a common factor for the layers that work or don't work... Do you have any idea?
Do you have a public link to share ?
Unfortunately, there is no public link... I sent you an email with username and password.
@loic74 : thank you for the access, it helped me found the bug. The issue was with accented layers. Here is fixed code :
lizMap.events.on({
attributeLayerContentReady: function(e) {
setTimeout(function(){
var cleanLayerName = lizMap.cleanName(e.featureType);
if( $('#attribute-layer-table-'+cleanLayerName+'_wrapper').data('filtersON') == undefined ){
// Set flag to add filters only once
$('#attribute-layer-table-'+cleanLayerName+'_wrapper').data('filtersON', true);
$('#attribute-layer-table-'+cleanLayerName+'_wrapper thead:first th').not('.sorting_disabled').each( function () {
var title = $(this).text();
$(this).html( '<input type="text" placeholder=" '+title+'" />' );
});
var table = $('#attribute-layer-table-'+cleanLayerName).DataTable();
table.columns().every( function () {
var column = this;
$( 'input', this.header() ).on( 'keyup change', function () {
if ( column.search() !== this.value ) {
column
.search( this.value )
.draw();
}
}).click(function(e) {
// We don't want to sort when users click on the search field
e.stopPropagation();
});
});
lizMap.refreshDatatableSize("#attribute-layer-main-"+cleanLayerName);
}
}, 500);
}
});
Well done. After clearing the browser cache, everything works fine. Thank you again.
@josemvm @loic74 I've updated my last answer to fix a bug.
nice @nboisteault thanks :-)
@nboisteault can you add your code here: https://github.com/3liz/lizmap-javascript-scripts
@rldhont https://github.com/3liz/lizmap-javascript-scripts/pull/1
The script works fine, it’s really useful. To have a correct result of a search we need to write “string to search”, otherwise the result won’t be exactly equal to the string. For example, if we write pozzo 3 the resulting records are referred to pozzo 3, pozzo 13, pozzo 31 etc . Is it possible to insert the “ “ directly in the script? Other improvements could be: a button X to clear previous search and resize column width in function of the length of the field name.
@tethysgeco you can replace :
column
.search( this.value )
.draw();
by
column
.search( this.value, true, false )
.draw();
to tell datatables to match exactly the string. Reference.
I have updated my code here to tell how to active filter only on specific columns. I'll publish another example with checkboxes dropdowns later.
We tried to add an array of coloumns but we didn't manage it. Could you provide us an example? Sorry but we aren't expert in js. Thanks
I tried to use the code but nothing happens when I open the attribute table. Is there something to configure before ?
@Cww7 Yes, look at comment
// You can put an array of index in columns() to tell on which column you want the search input to appear.
You have to add an array with indexes of the column you want a filter on. An example :
$('#attribute-layer-table-'+cleanLayerName).dataTable().api().columns([2, 3]).every( function () {
Nothing change... No need to indicate the attribute layer ?
Do you have a public link to share ?
No, unfortunately... I usually use other js scripts and it works. My tables are on postgresql 11.5 database, with Lizmap 3.3 and Qgisserver 3.4. I have to think about it but I have no solution for the moment.
@Cww7 I have updated the script to fix a bug. All columns of every layers have filter active by default, I'll add a way to configure that later.
It works great !! Thx @nboisteault !