[PL] Aurora Frontend Functionalities Get Noticed 2016 TypeScript

Śledzenie wartości property w Aurelia.io przy pomocy BindingEngine

Ostatni wpis konkursowy zakończyliśmy stwierdzeniem, że sztywne pisanie metod, które są podpięte pod przyciski stronicowania to słabe rozwiązanie. Przy okazji, jeżeli ktoś tego wpisu nie czytał to serdecznie zapraszam tu 🙂 Zdecydowanie lepszym rozwiązaniem byłoby śledzenie wartości property w ViewModel-u i reagowanie na wszelkie zmiany. W knockout.js rozwiązalibyśmy to przy pomocy metody subscribe na obiekcie ko.observable, w angularze zaś do tego celu służy $watch. Aurelia.io nie pozostaje dłużna konkurencji oferując swoje rozwiązanie w postaci obiektu BindingEngine. Aby jednak tekst poniżej nie był tylko sztywnym przykładem/wzorem, użyjmy go do jednej z funkcjonalności w naszej aplikacji. Case jest prosty: podczas tworzenia nowego projektu chcielibyśmy mieć możliwość dodania do niego użytkowników systemu, tworząc nic innego jak zespół wytwórczy. Do tego celu potrzebujemy czegoś na wzór wyszukiwarki (nie chcemy przecież przedzierać się przez pełną listę użytkowników 😉 ). Zaimplementujemy więc mechanizm, który po wprowadzeniu pewnego ciągu znaków w inpucie wykona żądanie do serwera aplikacji w celu wyszukania potencjalnych członków zespołu. Tak jak w poprzednim wpisie, niżej prezentowany kod będzie jedynie niezbędnym minimum. „Okrojony” ViewModel wygląda następująco:

 

export class CreateProjectViewModel
{
    searchPhrase: string;
    users: userModels.UserModel[];
    newProject: models.ProjectCreateModel;
 
    private createProjectService: services.IProjectCreateService;
    private userService: userSerices.IUserService;
 
    constructor(createProjectService: services.ProjectCreateService, userService: userSerices.UserService, private bindingEngine: BindingEngine, private router: Router)
    {      
        this.createProjectService = createProjectService;
        this.userService = userService;
        this.newProject = new models.ProjectCreateModel();
 
        this.subscribeProperties();
    }
 
    subscribeProperties()
    {
        this.bindingEngine.propertyObserver(this, 'searchPhrase').subscribe((newValue, oldValue) => {
            if (newValue.length === 0) {
                this.users = [];
                return;
            }
 
            if (newValue.length < 3)
                return;
 
            this.findUsersBySearchPhrase();
        });
    }
 
    findUsersBySearchPhrase()
    {
        this.userService.findUsersBySearchPhrase(this.searchPhrase).then((result: userModels.UserModel[]) => {
            this.users = result;
        });
    }
//inne metody
}

 

Tak jak wspomniałem na początku, niezbędnym elementem naszej implementacji jest import BindingEngine. W konstruktorze ViewModelu należy zasubskrybować property, którego stan chcemy śledzić. Ponieważ jednak nie chcemy zaśmiecać konstruktora, wszystko wynieśliśmy do metody subscribeProperties. Sam mechanizm jest dosyć prosty. Metoda propertyObserver przyjmuje dwa parametry: obiekt, którego property chcemy śledzić oraz nazwę właściwości (bardziej niż string pasowałoby mi arrow function, no ale pewnie był ku temu powód). Następnie w metodzie subscribe możemy umieścić logikę realizowaną przy zmianie wartości property. Warto także zwrócić uwagę, że posiadamy dostęp do wartości przed i po zmianie stanu. W naszym przypadku logika nie jest skomplikowana. Jeżeli długość szukanej frazy jest równa zero, zawartość tablicy users zostaje „usunięta” (ponieważ użytkownik najprawdopodobniej skasował tekst w polu wyszukiwania), a żądanie nie zostanie wysłane na serwer. Jeżeli natomiast długość frazy jest krótsza od trzech, wtedy jedynie pomijamy żądanie (długość frazy mogłaby spowodować zwrócenie zbyt dużej liczby rekordów). Tu jednak pojawia się problem. W momencie wpisywania frazy w inpucie, metoda subscribe byłaby wywoływana każdorazowo po dodaniu/usunięciu litery. Aby maksymalnie ograniczyć liczbę żądań AJAX-owych warto byłoby opóźnić w pewien sposób Aurelie, aby dać czas użytkownikowi na wpisanie treści. W tym celu wykorzystamy  parametr debounce umieszczony w elemencie HTML. Implementacja wygląda następująco:

 


<input id="project-create-search" value.bind="searchPhrase & debounce:500" type="text">

 

Dzięki temu zabiegowi zmiana wartości pola  zostanie „zauważona” po 500 milisekundach. Czas sprawdzić jak działa nasz mechanizm:
Animation

 

Efekt jest zgodny z założeniami 🙂 Na dziś to wszystko. Mam nadziej, że mimo krótkiej treści wpis przyda się osobom, które zapoznają się  z Aurelią. Przypominam Wam, że cały kod projektu macie dostępny na githubie. Zachęcam również do śledzenia mnie na twitterze i facebooku. A my widzimy się już za kilka dni 😉