Problém

Column filtr (dále „sloupcový filtr“) plugin (http://code.google.com/…lumn-filter/) pro jquery plugin DataTables (http://datatables.net/) zlobí, když se na jedné stránce vyskytnou dvě nebo více tabulek (typu datatable). Sloupcový filtr pak chybně filtruje pouze poslední definovanou tabulku. V praxi to vypadá tak, že když se pokusíte použít sloupcový filtr např. první tabulky, filtruje se úplně jiná tabulka – ta poslední.

Upozornění

Používám colum jquery.dataTa­bles.columnFil­ter.js verzi 0.9, která je jediná ke stažení na oficiálních stránkách zde – http://code.google.com/…wnloads/list (v době psaní tohoto článku). Sice lze najít v svn trunku vyšší verzi (http://jquery-datatables-column-filter.googlecode.com/…umnFilter.js), v době psaní tohoto článku konkrétně 1.5, ale ta mi narozdíl od verze 0.9 nefunguje (a nevím proč), takže nemohu vyzkoušet, jestli je tam stejný problém.

Řešení

Řešení bude modifikovat soubor jquery.dataTa­bles.columnFil­ter.js, pokud tedy používáte jinou verzi než 0.9, je možné, že se jednotlivé řádky mohou více či méně lišit, ale oprava problému je principiálně jednoduchá, takže věřím, že řešení bude použitelné i v jiných verzích.

Naprosto stejný problém se řeší i zde: http://datatables.net/…same-page/p1 a je tam moje odpověď, jak vyřešit tento problém drobnou modifikací zdrojového souboru jquery.dataTa­bles.columnFil­ter.js. Následující řádky jsou volným přepisem této mé odpovědi do češtiny:

Veškerý níže zmiňovaný kód se týká souboru jquery.dataTa­bles.columnFil­ter.js. Problém začíná na tomto řádku:

$.fn.columnFilter = function (options) {
        oTable = this;

Globální proměnná oTable nabude hodnoty poslední tabulky, kterou definujeme. Funkce fnCreateInput se stará o vytváření input elementu používaného pro textové filtrování (ostatní typy filtrovaných polí jako date-range, number-range jsou víceméně analogické) a má tento předpis:

function fnCreateInput(regex, smart, bIsNumber) {

uvnitř je tento kód:

if (bIsNumber && !oTable.fnSettings().oFeatures.bServerSide) {
    input.keyup(function () {
        /* Filter on the column all numbers that starts with the entered value */
        oTable.fnFilter('^' + this.value, index, true, false);
    });
} else {
    input.keyup(function () {
        /* Filter on the column (the index) of this element */
        oTable.fnFilter(this.value, index, regex, smart);
    });
}

input.keyup se zavolá, když uživatel začne psát do filtr inputu a spustí se filtrování. Problém je proměnná oTable, která má nyní hodnotu poslední definované tabulky. Jednoduché řešení spočívá ve změně proměnné oTable z globální na lokální:

function fnCreateInput(regex, smart, bIsNumber, oTable) {

Totéž musíte udělat i pro další funkce, které generují jiné typy sloupcového filtrování:

function fnCreateInput(regex, smart, bIsNumber, oTable)

function fnCreateRangeInput(oTable)

function fnCreateDateRangeInput(oTable)

function fnCreateSelect(aData, oTable)

A nakonec je samozřejmě třeba předat těmto funkcím správný argument oTable v místě, kde se volají. K tomu dochází v této funkci:

$.fn.columnFilter = function (options) {

Zde najdete příkaz switch, kde najdete postupně volání všech zmiňovaných funkcí a předáte tam argument oTable, který má zde ještě správnou hodnotu (je tam aktuálně vytvářená tabulka):

switch (aoColumn.type) {
    case "number":
        fnCreateInput(true, false, true, oTable);
        break;
    case "text":
        bRegex = (aoColumn.bRegex == null ? false : aoColumn.bRegex);
        bSmart = (aoColumn.bSmart == null ? false : aoColumn.bSmart);
        fnCreateInput(bRegex, bSmart, false, oTable);
        break;
    case "select":
        fnCreateSelect(aoColumn.values, oTable);
        break;
    case "number-range":
        fnCreateRangeInput(oTable);
        break;
    case "date-range":
        fnCreateDateRangeInput(oTable);
        break;
    default:
        break;

A to je vše. Můžete si stáhnout celý modifkovaný columnFilter plu­gin

Závěr

Nejedná se rozhodně o univerzální řešení, ani nijak zvlášť hezké (jsme nuceni modifikovat knihovnu třetí strany), ale je funkční. Je možné, že jde skutečně o bug v této jinak dobré knihovně a nevím, zda je již vyřešen (špatně mi funguje dnes aktuální verze 1.5) nebo se v budoucnu vyřeší. Každopádně výše zmíněný postup vám může pomoci v případě stejného problému rychle rozběhat více tabulek datatables s column filtrem na jedné stránce a nemusíte nad tím strávit celý den jako já :-)

Komentáře

zahry před 5 lety

Díky za super článek: Určitě by bylo dobré tvé řešení dát přímo stáhnout. např pod článkem.

reagovat

Lukáš Knápek před 5 lety

Jo, to je dobrý nápad, před sekcí Závěr je nyní odkaz na kompletní modifikovaný soubor columnFilter plugin, díky.

reagovat

Martin před 2 lety

Ahoj,

Mám trochu jiný problém s tímto pluginem, ale zkusím se zeptat zde, jestli ses náhodou nesetkal s něčím podobným.. Na stránce mám asp:CheckBox a u něho definovaný event handler OnCheckedChanged.. s tímto pluginem mi přestal fungovat tento handler, když CheckBox odškrtnu.. Při zaškrtnutí vše funguje v pořádku, ale při odškrtnutí se ten event handler vůbec nezavolá (při debuggování). Všude píšou, že musím nastavit EnableViewState na true, ale to mi nepomohlo.. AutoPostBack mám taky na true.. Problém musí asi být někde v tomto pluginu.. mám verzi 1.5.6. Díky za případnou pomoc.

reagovat

Přidat komentář

  • Můžete použít Texy syntaxi, HTML není povoleno
  • Například: *kurzíva*, **tučně**, "text odkazu":adresa
 

Autor článku Lukáš Knápek

Od roku 2008 věnuji víceméně dobrovolně třetinu života vyvíjení webových aplikací, především prostřednictvím těchto jazyků a nástrojů: Java, Struts2, Hibernate, Spring, Maven, Dojo, JQuery, Tomcat a Eclipse. A to vše s vírou, že to bude užitečné nejen k vydělávání peněz pro potřeby Lukáše Knápka :-)