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

A cikksorozat előző részeiben ([1], [2]) az egyszeri adatkötéssel ismerkedtünk, ami sok esetben nagyon hasznos, de mégis az az igazi, ami a megváltozott adatot automatikusan képes frissíteni a felhasználói felületen. Ehhez arra van szükségünk, hogy észrevegyük, ha egy objektum valamelyik tulajdonsága megváltozik, ami lássuk be, JavaScriptben nem is olyan egyszerű feladat.

JavaScriptben ugyanis nincsenek property-k, legalábbis nem a .NET-es értelemben, azaz nincs lehetőségünk getter és setter metódusok írására. Ugyan van egy javasolt elnevezési konvenció – amit egyébként a Microsoft AJAX Library osztályai követnek is – miszerint írjunk get_ és set_ kezdetű metódusneveket, de ez nagyon körülményes megoldás lenne olyan esetekben, amikor primitív adatstruktúrákkal dolgozunk. Képzeljünk el egy webszolgáltatástól JSONban visszakapott Person objektumokból álló tömböt, hol van abban get_ és set_ metódus? Sehol.

Hasonló problémákra az elterjedt megoldás az observer tervezési minta használata: adott egy publisher, akinek a birtokában van az adat és ő szól az érdeklődő subscribereknek, ha az adat megváltozott. Egy JSONos objektum tömb valóban tartalmazza az adatot, csak éppen nem képes szólni, ha az megváltozik. Természetesen nincs akadálya, hogy felruházzuk a tömbünket ilyen funkciókkal, de ha ezt minden esetben nekünk kell megírnunk, akkor az egyrészt nagyon sok munka (JavaScriptben a sima “sok”=”brutál sok”), másrészt nagyon idegesítő lesz a sokféle implementációval vacakolni.

Itt jön a képbe a Sys.Observer osztály, ami képes egy tetszőleges objektumot igazi publisherré tenni.

Vegyük a korábban már látott országokat egy tömbben:

  var countries = [
        { Name: 'Austria', Capital: 'Vienna' },
        { Name: 'Australia', Capital: 'Canberra' },
        // És így tovább...
    ];

És jelenítsük meg a már jól ismert DataView vezérlővel deklaratív módon:

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

Készítsünk két linket, amivel a forrás adatokat manipuláló függvényeket fogjuk hívni:

  <a href="#" onclick="onAdd()">Hozzáad</a> 
  <a href="#" onclick="onDelete()">Töröl</a>

Ezek után, ha az onAdd és onDelete függvényekben megpróbáljuk közvetlenül módosítani a countries változót, akkor hiába várjuk, hogy a módosítások megjelenjenek a felületen. Nosza vessük be a Sys.Observer osztályt és tegyük a countries gyűjteményt observable-lé:

  Sys.Observer.makeObservable(countries);

Majd figyeljük meg például a Visual Studio Watch ablakában, hogy hogyan változott a saját kis primitív adatstruktúránk: Sys.Observer.makeObservable eredménybe

A gyűjteményünk kapott néhány metódust és ha ezeket használjuk az adatok módosítására, akkor arról minden subscriber értesülni fog. A metódusok nevei eléggé magukért beszélnek, egyedül annyit emelnék ki, hogy ha nem akarjuk az értesítést azonnal elküldeni – például mert több tulajdonságot módosítunk sorban – akkor a módosítások előtt hívjuk meg a beginUpdate, a végén pedig az endUpdate metódust. Az előbbi felfüggeszti az értesítés küldést, az utóbbi pedig elküldi őket. A makeObservable metódust egyszerűbb esetekben akár el is hagyhatjuk, ekkor azonban a Sys.Observer osztály “statikus” metódusainak első paraméteréül át kell adnunk, hogy melyik objektummal dolgozzanak.

Visszatérve a fenti példára, írjuk meg az onAdd és onDelete metódusokat az új metódusok segítségével:

  function onAdd()
  {
    countries.add({ Name: 'France', Capital: 'Paris' });
  }

  function onDelete()
  {
    countries.removeAt(9);
  }

Ezzel készen is vagyunk, ha kipróbáljuk látni fogjuk, hogy a gyűjtemény módosításai azonnal látszódnak a felhasználói felületen, nem kell külön frissítenünk. Már csak azzal vagyok adós, hogy miért? A megoldás pedig igen egyszerű: a DataView okos osztály, észreveszi, hogy observable adatforrással dolgozik és automatikusan feliratkozik a változásaira, nekünk ezzel nem kell foglalkoznunk.

Érdemes kipróbálni, hogy mi történik, ha nem a gyűjteményen, hanem a gyűjtemény egyik elemén módosítunk, például így:

  countries[7].Name = 'Magyarország';

Megmondom már most: semmi, a DataView rá se bagózik. De hogy mindennek mi köze a live bindinghoz, azt azonban csak legközelebb árulom el…

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

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