Autouzupełniający się filtr combobox dla Ext JS 4 Grid (CRUD)

Autouzupełniający się filtr combobox dla Ext JS 4 Grid (CRUD)

Cześć, w tym artykule pokażę Ci jak utworzyć filtr (input) z automatycznymi podpowiedziami, coś podobnego do działania wyszukiwarki google. W przykładzie użyję listy z użytkownikami, których będzie można filtrować. Po stronie serwera jest Zend FrameworkDoctrine oraz funkcjonalnością CRUD. Możesz użyć czegoś innego, np node.js ponieważ sposób użycia jest identyczny.

Mój grid wygląda tak jak poniższe zdjęcie:

34-extjs4

1. Combo box

35-extjs4

W docked items w funkcji initComponent Grid proszę dodaj pole field container z combo box:

this.dockedItems = [
            {
                xtype: 'toolbar',
                dock: 'top',
                items: [
                    {
                        xtype: 'button',
                        itemId: 'usersAdd',
                        text: 'Add user'
                    },
                    {
                        xtype: 'container',
                        flex: 1
                    },
                    {
                        xtype: 'fieldcontainer',
                        layout: 'hbox',
                        items:[
                            {
                                xtype: 'combobox',
                                anchor: '100%',
                                fieldLabel: '',
                                hideTrigger: true,
                                displayField: 'login',
                                minChars: 1,
                                queryDelay: 250,
                                store: Ext.create('DevJS.store.Users', {storeId: 'usersFilter'}),
                                queryParam: 'value',
                                typeAheadDelay: 200,
                                itemId: 'filter',
                                valueField: 'login'
                            },
                            {
                                xtype: 'button',
                                iconCls: 'button-search',
                                itemId: 'doFilter',
                                text: ''
                            }
                        ]
                    }
                ]
            },
            {
                xtype: 'pagingtoolbar',
                dock: 'bottom',
                width: 360,
                displayInfo: true,
                store: 'Users'
            }
        ];

2. Store

Teraz musisz utworzyć dodatkową instancję store z użytkownikami. W tym przypadku wystarczy stworzyć nowy store z innym storeId. Robimy tak aby zapobiec filtrowaniu głównego store, który jest podpięty do widoku Ext JS Grid:

36-extjs4

Jak zauważyłeś kod ma wpływ na dwa miejsca (pole combo box oraz widok Grid). Niektórzy użytkownicy mogą polubić taki sposób lecz główna lista powinna się filtrować dopiero jak użytkownik wciśnie klawisz enter lub użyje myszy.

Kod źródłowy dla store wygląda następująco:

Ext.define('DevJS.store.Users', {
    extend: 'Ext.data.Store',
    model: 'DevJS.model.User',
    autoLoad: true,
    autoSync: true,
    remoteFilter: true,

    proxy: {
        type: 'direct',
        api: {
            read : 'Core.User.read',
            create : 'Core.User.create',
            update : 'Core.User.update',
            destroy : 'Core.User.destroy'
        },
        reader: {
            type: 'json',
            root: 'User'
        }
    }
});

Zmienna remoteFilter jest odpowiedzialna za sposób filtrowania, jeśli chcesz filtrować swój store lokalnie wystarczy ustawić ją na wartość false.

Jak to działa?

a) standardowy sposób ładownia store – wysyła zapytanie do serwera bez żadnej dodatkowej wartości, oznacza to, że twoja metoda Read na serwerze powinna wysłać wszystkie rekordy

39-extjs4

b) combox filter load – sposób ładowania combox jest już bardziej złożony, posiada wbudowany parametr w zapytaniu. Parametr ten wysyłany jest do serwera za każdym razem gdy użytkownik wywoła listener “change” oraz liczba znaków będzie spełniać warunek > minChars (w naszym przypadku 1). W tablicy filter znajduje się zmienna “property”, która w tym przypadku ma wartość “login”. Oznacza pole po jakim mamy filtrować

38-extjs4

c) store filter load – jest bardziej skomplikowana, dzięki niej możesz użyć więcej niż jednej właściwości w tablicy filter i wysyłać więcej niż jedno pole do filtrowania, ale w tym przykładzie wystarczy jedna, czyli “login”

40-extjs4

Teraz musisz dostosować metodę read do tej funkcjonalności. W tym przykładzie używam Zend Framework wraz Doctrine, więc napisałem dla wszystkich metod Read  specialną funkcję do filtrowania wartości.

public function read($params)
    {
        $qb = $this->em->createQueryBuilder();
        $qb->select('u')
            ->from('Core\Entity\User', 'u');

        $query = $this->filter($params, $qb, 'u')->getQuery();

        $results = $query->getArrayResult();

        return array('success'=>true, 'User' => $results);
    }

Rezultat w postaci json:

37-extjs4

3. Events

Proszę przejdź do kontrolera, w tym przypadku Users Controller.

a) listener dla akcji w funkcji init(this.control({}))

'usersList > toolbar > fieldcontainer > button[itemId=doFilter]': {
                click: me.onUsersFilterClick
            }

b) funkcja filter

onUsersFilterClick: function(button, e, eOpts) {
        var me = this, field = me.getUsersList().down('toolbar > fieldcontainer > combobox[itemId=filter]');

        me.getUsersList().getStore().clearFilter(true);
        me.getUsersList().getStore().filter('login', field.getValue());
    }

Funkcja clearFilter czyści wspomnianą wcześniej tablicę filter a przekazana wartość true zapobiega dodatkowemu zapytaniu do serwera, ponieważ metoda filter robi to samo tylko już z nowymi wartościami. Ale jeśli chcesz tylko wyczyścić filtr i przywrócić poprzedni stan store, nie musisz przekazywać do funkcji żadnej wartości.

//bez użycia funkcji clearFilter wartości będą dodawane za każdym razem do już istniejących

Bonus!

Funkcjonalność klawisza enter. Sposób użycia: użytkownik wypełnia pole textfield i wciska klawisz enter aby przefiltrować listę użytkowników:

a) czyli, dodajemy nowy action listener

'usersList > toolbar > fieldcontainer > combobox[itemId=filter]': {
                select: {
                    fn: me.onUsersFilterSelect,
                    scope: me
                }
            },

b) funkcja select

onUsersFilterSelect: function(combo, records, eOpts) {
        combo.nextSibling().fireEvent('click');
    }

To wszystko. Teraz twój użytkownik może użyć klawisza enter lub kliknięcia myszą.

4. Rezultat

Końcowy Grid wraz z nową funkcjonalnością wygląda tak jak przedstawia poniższe zdjęcie:

41-extjs4

Udanej zabawy i do później.

Komentarze:

Zostaw odpowiedź

Proszę wypełnij wymagane pola aby dodać komentarz.


Drag circle to the rectangle on the right!

Wyślij