Ostatnio miałem przyjemność poznać i przetestować możliwości frameworka JavaScript: ExtJS. Jest to biblioteka przeznaczona do budowania zaawansowanych interfejsów użytkownika, w szczególności paneli administracyjnych.
W niniejszym wpisie chciałbym na prostym przykładzie zademonstrować możliwości jednego z komponentów tego potężnego frameworka - GridPanel . Jeszcze nie wiem czy będzie to część większego cyklu kursów o extjs i czy pojawi się on także w wersji angielskiej (wersja angielska - dodatkowo zaktualizowana dla Symfony 1.4 i Doctrine), ale narazie w planie mam wpisy dotyczące integracji z zaawansowanym systemem filtrów (ExtJS filter plugin) i dodawania/edytowania elementów do grida za pomocą modalnych okien - o ile oczywiście tematyka tego wpisu spotka się z zainteresowaniem.
Konfiguracja
Niezbędna konfiguracja dla tutoriala:
- dowolny serwer z obsługa PHP w wersji co najmniej 5.2.4 + baza danych MySql;
- zainstalowany framework Symfony w wersji 1.2.X (nic nie stoi na przeszkodzie by wypróbować sf 1.3) lub ewentualnie sandbox do pobrania (piaskownica Symfony- wstępnie skonfigurowany framework gotowy do pracy od zaraz);
- dostęp do wiersza poleceń;
Rozpoczynamy prace
Mając tak przygotowane środowisko należy utworzyć nowy projekt, wygenerować aplikacje frontendu (w przypadku korzystania z piaskownicy jest już wygenerowana) i przykładowy moduł, np: grid. By tego dokonać w katalogu projektu z wiersza poleceń należy wykonać kolejno:
symfony generate:project sfExtTest symfony generate:app frontend symfony generate:module grid
Połączenie z bazą danych i dane testowe
Dla naszego prostego przykładu moglibyśmy wykorzystać statyczne dane utworzone w JavaScript, jednakże chce pokazać przepływ danych między aplikacją klienta, a serwerem i bazą danych (między framewrokiem ExtJS, a Symfony i bazą danych), także niezbędna będzie dodatkowa konfiguracja.
Należy skonfigurować połączenie z bazą danych, utworzyć testowe tabele i wczytać do nich dane testowe. Poniższy kod odpowiada za wymienione powyżej elementy (poniższe dane zostały już wcześnie wykorzystane w tutorialu).
Konfiguracja połączenia z bazą danych:
symfony configure:database “mysql:host=localhost;dbname=twojaBazaDanych” uzytkownik haslo
Struktura tabeli testowej:
propel:
country:
_attributes: { phpName: Country }
id:
name: varchar(50)
description: varchar(255)
created_at:
Dane testowe:
Country:
Country_1:
name: 'Poland'
description: 'Description for Poland'
Country_2:
name: 'Germany'
description: 'Description for Germany'
Country_3:
name: 'Brazil'
description: 'Description for Brazil'
Country_4:
name: 'USA'
description: 'Description for USA'
Country_5:
name: 'Ireland'
description: 'Description for Ireland'
Country_6:
name: 'Canada'
description: 'Description for Canada'
Country_7:
name: 'India'
description: 'Description for India'
Country_8:
name: 'Italy'
description: 'Description for Italy'
Country_9:
name: 'Spain'
description: 'Description for Spain'
Country_10:
name: 'Portugal'
description: 'Description for Portugal'
Country_11:
name: 'Argentina'
description: 'Description for Argentina'
Country_12:
name: 'Estonia'
description: 'Description for Estonia'
Country_13:
name: 'Bulgaria'
description: 'Description for Bulgaria'
Country_14:
name: 'France'
description: 'Description for France'
Country_15:
name: 'Belgium'
description: 'Description for Belgium'
Country_16:
name: 'Austria'
description: 'Description for Austria'
Country_17:
name: 'Australia'
description: 'Description for Australia'
Country_18:
name: 'Japan'
description: 'Description for Japan'
Country_19:
name: 'Russia'
description: 'Description for Russia'
Country_20:
name: 'Slovakia'
description: 'Description for Slovakia'
Country_21:
name: 'Ireland'
description: 'Description for Ireland'
Teraz wystarczy z poziomu lini komend wywołać kolejno:
symfony propel:build-sql symfony propel:build-model symfony propel:insert-sql symfony propel:data-load
ExtJS
Następnym krokiem jest pobranie najnowszej wersji (3,0) biblioteki ExtJs. Całość ściągamy z oficjalnej strony EXTa i wypakowujemy do katalogu ext.
W tym momencie warto dokonać konfiguracji pliku view.yml, tak by framework automatycznie załączył odpowiednie biblioteki js i css (zmian należy dokonoać w pliku app/frontend/config/view.yml):
stylesheets: - ../js/ext/resources/css/ext-all.css javascripts: - ext/adapter/ext/ext-base-debug.js - ext/ext-all-debug.js
Zalecane jest by kod JavaScript organizować w osobnych plikach JS, jednakże w tym wypadku kod odpowiedzialny za wyświetlanie grida umieścimy w widoku akcji index modułu Grid.
By móc w ogóle przystąpić do pracy z komponentem grida trzeba poznać przynajmniej podstawy jego budowy i elementy składowe. Zasadniczo na GridPanel składa się 4 elementy:
- Store - obiekt odpowiedzialny za przechowywanie danych, w tym komunikację z serwerem - w naszym przypadku JsonStore;
- Column model - konfiguracja wyświetlania poszczególnych kolumn (m.in. opcje renderowania);
- View - specyficzne ustawienia efektów wyświetlania;
- Selection model - element nieobowiązkowy, odpowiada za operacje na kolumnach (zaznaczanie, pobieranie zaznaczonych) - postaram się pokazać zastosowanie tego komponentu w osobnym wpisie;
Także aby wyświetlić podstawową wersję grida potrzebujemy danych, konfiguracji kolumn, które chcemy wyświetlić i konfiguracji widoku (grid przyjmuje również dodatkowe opcje konfiguracyjne opisane szczegółowo w dokumentacji).
Poniższy kod odpowiada za wszystkie wyżej wymienione elementy (kod pliku: apps/frontend/modules/grid/templates/indexSuccess.php):
<div id="grid-example"> </div>
<?php javascript_tag(); ?>
Ext.onReady(function() {
// komponent odpowiadający za połączenie z serwerem
var store = new Ext.data.JsonStore({
root: 'result',
totalProperty: 'total', //całwkoita ilość zwracanych danych
idProperty: 'id',
id: 'id',
remoteSort: true, // sortowanie po stronei serwera
fields: ['id', 'name', 'description', 'created_at'], // struktura zwracanych elementów
url: 'grid/list', // adres url na serwerze
autoLoad: true // automatyczne ładowanie danych
});
//struktura kolumn
var columns = [
{id:'name',header: 'Państwo', width: 160, sortable: true, dataIndex: 'name'},
{header: 'Opis', width: 160, sortable: false, dataIndex: 'description'},
{header: 'Data utworzenia', width: 100, sortable: true, dataIndex: 'created_at'}
];
// obiekt grida
var grid = new Ext.grid.GridPanel({
title: 'Symfony 1.2 and Ext.js example',
loadMask: true, //maskowanie ładowania danych
store: store,
columns: columns,
autoExpandColumn: 'name',
height: 400,
width: 600,
renderTo: 'grid-example' // element DOM do którego ma być załadowany grid
});
});
<?php end_javascript_tag(); ?>
By całość mogła poprawnie działać nalezy utowrzyć dodatkową akcje “list”, z której komponent store będzie pobierał dane do grida (kod pliku: apps/frontend/modules/grid/actions/actions.class.php):
<?php
public function executeList(sfWebRequest $request) {
// tymczasowe dane ustawione na sztywno
$limit = 15;
$page = 1;
// pomocniczy obiekt odpowiedzialny za stronicowanie
$pager = new sfPropelPager('Country', $limit);
$pager->setPage($page);
$pager->init();
$result = array();
foreach($pager->getResults() as $country) {
$result[] = $country->toArray(BasePeer::TYPE_FIELDNAME);
}
// sformatowane dane są zwracane do grida
return $this->renderText(json_encode(array(
'total' => $pager->getNbResults(),
'result' => $result
)));
}
?>
W tym momencie można sprawdzić działanie kodu wywołując w przeglądarce adres:
http://localhost/nazwa-aplikacji/web/grid
Powinniśmy ujrzeć grida podobnego do tego przedstawionego na rysunku poniżej:
Obsługa stronicowania i sortowania
Obecna postac grida jest dość niewygodna, o ile w przypadku kilkunastu rekordów wyświetlanie ich na jednej stronie nie jest zbyt kłopotliwe, to w momencie gdy baza zacznie się rozrastać ładowanie wszystkich danych i operowanie na nich staje się niemal niemożliwe.
Za stronicowanie po stronie ExtJS odpowiada component: PagingToolbar. Jego kluczowym elementem jest zdefiniowany wcześniej komponent store. Kod odpowiedzialny za stronicowanie widoczny jest poniżej:
paging = new Ext.PagingToolbar({
pageSize: 10, // ilość elementów
store: store, // obiekt magazynujący dane
displayInfo: true, //wyśweitlanie dodatkowych informacji
displayMsg: 'Wyświetlanie państw {0} - {1} z {2}', // komunikaty
emptyMsg: "Lista państw jest pusta"
});
//małą modyfikacja kodu grida
var grid = new Ext.grid.GridPanel({
...
bbar: paging, // ustawiamy dolny panel grida
...
});
By stronicowanie i sortowanie działało prawidłowo modyfikacji wymaga akcja list, w której musimy zbudować odpowiednie zapytanie na podstawie parametrów żądania.
Modyfikacji wymaga też sama akcja executeList - musimy dodać do Niej obsługę stronicowania i sortowania po wybranej kolumnie:
<?php
public function executeList(sfWebRequest $request) {
// dane pobierane z żądania
$limit = $request->getParameter('limit', 10);
$page = $request->hasParameter('start') ? $request->getParameter('start')/$limit+1 : 1;
$dir = $request->getParameter('dir', 'asc');
$column = strtolower($request->getParameter('sort', 'name'));
# warunki dla sortowania
$c = new Criteria();
if (in_array($column, CountryPeer::getFieldNames(BasePeer::TYPE_FIELDNAME))) {
$column = CountryPeer::translateFieldName($column, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_COLNAME);
if ($dir == "ASC") {
$c->addAscendingOrderByColumn($column);
} else {
$c->addDescendingOrderByColumn($column);
}
}
# pomocniczy obiekt odpowiedzialny za stronicowanie
$pager = new sfPropelPager('Country', $limit);
# kryteria dla pagera
$pager->setCriteria($c);
$pager->setPage($page);
$pager->init();
$result = array();
foreach($pager->getResults() as $country) {
$result[] = $country->toArray(BasePeer::TYPE_FIELDNAME);
}
# sformatowane dane są zwracane do grida
return $this->renderText(json_encode(array(
'total' => $pager->getNbResults(),
'result' => $result,
'page' => $page
)));
}
?>
Teraz wystarczy tylko odświeżyć stronę i sprawdzić czy wszystkie zmiany zostały poprawnie naniesione - całość powinna wyglądać mniej więcej tak:


0 Responses to “Symfony 1.2 i ExtJS - wyświetlanie danych w gridzie”
Leave a Reply