ASP.NET AJAX 4: Kliens oldali adatkötés – alapok

Több, mint 2 éve, hogy először írtam lelkendezve a kliens oldali deklaratív adatkötésről. Akkor mindez az ASP.NET Futures részeként, mintegy előzetesként volt elérhető, és ahogy a 2007-es Web Konferencián be is mutattam, az XML-Script volt a fő csapásirány. Aztán tavaly nyáron jött a hír, hogy az XML-Script megy a kukába, és az ASP.NET AJAX-ban egy teljesen új megvalósítással fogunk találkozni.

Az ASP.NET AJAX 4.0 előzetesét háromféleképpen próbálhatjuk ki:

  • Visual Studio 2010: A fejlesztőeszköz és vele együtt a Framework jelen pillanatban béta 1 verzióban van és szabadon letölthető innen. Valószínűleg a novemberi PDC és TechEd idején lesz belőle béta 2 és majd valamikor jövő tavasszal RTM. A jó hír az, hogy simán fel lehet telepíteni VS 2008 és .NET 3.5 mellé, vígan futnak side-by-side. Persze ahogy mindig, ezt most sem célszerű production gépen kipróbálni, mert még nem tudjuk, hogy a béta 2-t és az RTM-t lehet-e majd olyan gépre telepíteni, amin volt béta 1, illetve, hogy a béta 1 eltávolítása simán fog-e menni. A másik saját tapasztalatom, hogy kiválóan használható remote desktopon keresztül is (ellentétben az egyik szakfolyóiratban megjelent WPF ostorozó cikkel).
  • ASP.NET AJAX Preview 5: Az ASP.NET csapat folyamatosan közzéteszi preview változatban az AJAX Library-t a CodePlexen. Az aktuális Preview 5 változat szabadon letölthető és kipróbálható VS 2008-on is.
  • Microsoft AJAX CDN: A Microsoft nemrég jelentette be, hogy az ASP.NET AJAX és jQuery Library-ket kipakolja Content Delivery Networkökre. Ez azt jelenti, hogy nem kell a JavaScript fájokat a saját webszerverünkön hosztolnunk, hanem elég megadnunk egy Microsoftos webkiszolgáló URL-jét és a böngésző onnan fogja letölteni a fájlokat. Ráadásul mindezt úgy, hogy a háttérben valójában a földrajzilag hozzánk legközelebbi webkiszolgálóval kommunikálunk, de az is lehet, hogy már egy másik webhely használta ezeket a fájlokat így megtalálhatóak a böngészőnk gyorsítótárában. A pontos URL-eket itt lehet megtalálni és érdemes kipróbálni, hogy egy tracert ajax.microsoft.com honnan nézve hány hop.

Mivel kliens oldali adatkötésről van szó, nincs szükségünk másra, csak az ASP.NET AJAX Library-höz tartozó JavaScript fájlokra. Az új verzió újdonsága, hogy szétszedték ezeket a script fájlokat és publikálták, hogy hogyan függnek egymástól:

ASP.NET AJAX Library szkript fájlok függőségei

Az aktuális bétában nincs ennyi fájl, csak core, AdoNet, DataContext, Templates és WebForms van. Ha csak az adatkötést használjuk, akkor a MicrosoftAjax.js és a MicrosoftAjaxTemplates.js fájlokra kell hivatkoznunk. Fontos látni, hogy ezek egyáltalán nem kapcsolódnak a szerver oldali ASP.NET-hez, ezért a technológia használható más környezetben is.

Ha ez kész, akkor létrehozhatunk a kódunkban egy pageLoad függvényt, amit a rendszer automatikusan meghív, miután az AJAX Library betöltődött. Szintén újdonság, hogy már nem kell meghívni a Sys.Application.initialize metódust, hogy ez megtörténjen:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>ASP.NET AJAX 4 (Preview 5) példakód (Balássy György)</title>
        <script type="text/javascript" 
src="http://ajax.Microsoft.com/ajax/beta/0909/MicrosoftAjax.js"></script> <script type="text/javascript"
src="http://ajax.Microsoft.com/ajax/beta/0909/MicrosoftAjaxTemplates.js"></script> <script type="text/javascript"> function pageLoad() { alert('Ez már ASP.NET AJAX 4!'); } </script> </head> <body> </body> </html>

Példánkban az adatforrás legyen egy objektum tömb országokkal és városokkal, amit egy felsorolt listában szeretnénk megjeleníteni:

  var countries = [
    { Name: 'Austria', Code: 'at', Capital: 'Vienna' },
    { Name: 'Australia', Code: 'au', Capital: 'Canberra' },
    { Name: 'Brasil', Code: 'br', Capital: 'Brasília' },
    { Name: 'Croatia', Code: 'cr', Capital: 'Zagreb' },
    { Name: 'Spain', Code: 'es', Capital: 'Madrid' },
    { Name: 'Finland', Code: 'fi', Capital: 'Helsinki' },
    { Name: 'Greece', Code: 'gr', Capital: 'Athens' },
    { Name: 'Hungary', Code: 'hu', Capital: 'Budapest' },
    { Name: 'Sweden', Code: 'se', Capital: 'Stockholm' },
    { Name: 'Slovakia', Code: 'sk', Capital: 'Bratislava' },
    { Name: 'United Kingdom', Code: 'uk', Capital: 'London' },
    { Name: 'United States', Code: 'us', Capital: 'Washington, D.C.' }
  ];

Adatkötés deklaratívan

Az adatkötés deklaratív leírásához újabb névtereket kell bevezetnünk a body elemben:

  <body xmlns:sys="javascript:Sys" xmlns:dv="javascript:Sys.UI.DataView">

Innen már csak egy lépés, hogy meg is jelenjenek az adatok:

  <ul
    class="sys-template"
    sys:attach="dv"
    dv:data="{{ countries }}" >
    <li>
        {{ Name }} ({{ Capital }})
    </li>
  </ul>

Kicsit (?) szokatlan a szintakszis, de nézzük sorban, mi ebben az extra!

class=”sys-template”

Ezzel kell megmondanunk a template engine-nek, hogy ezt a HTML DOM elemet adatkötéshez sablonként használjuk. Fontos, hogy ennek a CSS osztálynak léteznie kell és tartalmaznia kell a display: none; beállítást. (Ez egyébként okozhat problémát, például a Google Maps vezérlő nem szereti, ha láthatatlan állapotban akarjuk inicializálni.) Egyes források szerint a név bármi lehet, de tapasztalatom szerint nem működik minden, ha nem sys-template a neve.

sys:attach=”dv”

A sys és dv névtereket a body elemben definiáltuk és az AJAX Library névterére és osztályára mutatnak. A sys:attach segítségével egy létező osztály, jelen esetben a Sys.UI.DataView osztályt kapcsoljuk az aktuális HTML elemhez. Az adatkötés kulcsa tehát a kliens oldali új DataView vezérlő.

dv:data = “{{ countries }}”

Mivel a dv névteret a body elemben definiáltuk, ezzel a szintakszissal állíthatjuk be a DataView osztály tulajdonságait. A data tulajdonságot akkor használjuk, ha egy rendelkezésre álló JavaScript objektumhoz vagy tömb változóhoz szeretnénk kötni, jelen esetben a korábban létrehozott countries tömb a kedvezményezett. A DataView képes magát akár webszolgáltatásból is feltölteni, aminek beállításához a dataprovider, fetchoperation, fetchparameters, httpverb és autofetch tulajdonságokat használhatjuk.

{{ Name }} és {{ Capital }}

A {{ }} blokkban tetszőleges JavaScript kifejezés állhat, ami az adatkötés során minden egyes rekordnál ki fog értékelődni. Ezen belül hivatkozhatunk az aktuális rekord tulajdonságaira, mint a fenti példában a countries tömb egyes elemeinek Name és Capital mezőire.

Adatkötés kódból

A fenti kódrészletet joggal érheti az a vád, hogy kusza, keveredik benne a logika és a megjelenítés. Szerencsére van lehetőség az adatkötést leválasztani a HTML markupról, ez esetben viszont kódhoz kell fordulnunk. A vezérlők felkonfigurálását az application init eseménykor célszerű elvégezni, ezért fel kell rá iratkoznunk:

  Sys.Application.add_init(appInit);

Ebben az eseménykezelőben létrehozhatjuk a DataView vezérlőnket az AJAX Library $create(type, properties, events, references, element) metódusával és ráhúzhatjuk a HTML markupban id=”list” attribútummal ellátott elemre:

  function appInit()
  {
    var dv = $create(
        Sys.UI.DataView,
        {
          data: countries                    
        },
        {
          itemRendered: onItemRendered
        },
        null,
        $get("list")
    );
  }

A korábbiakhoz képest új, hogy fel kell iratkoznunk az itemRendered eseményre is, mert ott tudjuk az egyes rekordokhoz tartozó adatkötéseket konfigurálni. Ha esetleg már létezne ilyen DataView vezérlőnk és csak az adatforrását kívánjuk állítani, akkor azt legegyszerűbben így tehetjük meg:

  $find('list').set_data(countries);

Ezek után a markup sokkal letisztultabb, még a body tagről is lekerült a dv névtér:

  <ul
    id="list"
    class="sys-template">
    <li>
        <span sys:key="Name"></span>
        (<span sys:key="Capital"></span>)
    </li>
  </ul>

A sys:key attribútumok célja, hogy az egyes rekordok renderelésekor megtaláljuk a helyet, ahol az adatokat megjelenítjük. Ehhez Sys.Binding objektumokat hozhatunk létre az onItemRendered eseménykezelőben:

  function onItemRendered(sender, e)
  {
    var context = e.get_itemContext();
    var dataItem = e.get_dataItem();

    $create(
        Sys.Binding,
        {
            source: dataItem,
            path: "Name",
            target: context.keys.Name,
            targetProperty: "innerHTML"
        }
    );

    $create(
        Sys.Binding,
        {
            source: dataItem,
            path: "Capital",
            target: context.keys.Capital,
            targetProperty: "innerHTML"
        }
    );                
  }

Természetesen arra is van lehetőség, hogy teljesen megszabaduljunk a sys: névtértől. Ebben az esetben id attribútum kell minden span elemre:

    <body>
        <ul
            id="list"
            class="sys-template">
            <li>
                <span id="Name"></span>
                (<span id="Capital"></span>)
            </li>
        </ul>
    </body>

A Sys.Binding objektumok létrehozását pedig úgy kell átírnunk, hogy az id attribútum alapján találjuk meg az adatok helyét:

  $create(
    Sys.Binding,
    {
        source: dataItem,
        path: "Capital",
        target: $get('Capital', context),
        targetProperty: "innerHTML"
    }
  );    

Ez az adatkötés legegyszerűbb formája: egyirányú, lokális változóból dolgozik, de nem veszi észre annak a változásait. Mindhárom irányba lehetne bővíteni a példát, a rendszer képes kétirányú adatkötésre, a DataView pedig fel tudja magát tölteni akár egy WCF szolgáltatás meghívásával és a változásokat automatikusan meg is tudja jeleníteni, sőt akár a szerverre is vissza tudja frissíteni. De ezekről majd legközelebb…

A cikkhez tartozó forráskód letölthető innen és innen.

One thought on “ASP.NET AJAX 4: Kliens oldali adatkötés – alapok

  1. Visszajelzés: Ne várakoztasd a felhasználót: jQuery Templates és ASP.NET PageMethods « Balássy György szakmai blogja

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s