#Angular2 – Sortowanie i usuwanie dokumentów

W święta znalazłem chwile czasu, na to, aby popracować nad projektem. Do tego wpisu chciałem już zrobić dodawanie i usuwanie dokumentów, jednak nie udało mi się z tym wyrobić. Z założeń z poprzedniego wpisu, dodałem jedynie usuwanie i zaznaczanie wszystkich dokumentów. Nigdy nie zastanawiałem się nad działaniem checkboxa, który zaznacza wszystkie checkboxy, a jednak trochę kodu do jego obsługi trzeba było napisać.

W pierwszej kolejności postanowiłem dodać sortowanie w kolumnach. Musiałem znów zajrzeć do API. Dodałem kolejne dwie zmienne pobierane z GET’a:

$orderBy = $request->query->get('order_by', '');
$sorting = $request->query->get('sorting', '');

No i w repozytorium musiałem dodać kolejne dwa if’y:

if($orderBy!='')
{
    if($orderBy == 'number' || 
        $orderBy == 'type' || 
        $orderBy == 'date' || 
        $orderBy == 'dateOfPayment' || 
        $orderBy == 'paymentMethod' || 
        $orderBy == 'paid')
    {
        $orderBy = 'ORDER BY d.'.$orderBy;
    }else if($orderBy == 'consumer'){
        $orderBy = 'ORDER BY c.name';
    }else{
        $orderBy = '';
    }
}
if($sort!='')
{
    if(($sort == 'ASC' || $sort == 'DESC') && $orderBy != '')
    {
        $sort = $sort;
    }else{
        $sort = '';
    }
}

W usłudze dokumentu musiałem też wydłużyć trochę adres i dodać 2 nowe parametry:

http://localhost:8000/api/documents?type={typ}&from={data_od}&to={data_do}&search={ciag_znakow_do_wyszukiwania}&order_by={pole_sortowania}&sorting={kierunek_sortowania}

Teraz już tylko w Angularze dodałem zmienne odpowiedzialne za te dwa nowe parametry i dodałem dwie funkcje:

sortingBy(by)
{
    if(this.orderBy == by)
    {
        if(this.sorting == 'DESC')
        {
            this.sorting = 'ASC';
        }else{
            this.sorting = 'DESC';
        }
    }else{
        this.sorting = 'ASC';
        this.orderBy = by;
    }
    this.searchDocuments();
}

order(item)
{
    let result = '';
    if(this.orderBy == item)
    {
        result = this.sorting;
    }
    return result;
}

Pierwsza z nich ustawia odpowiedni parametr dla sortowania. Przy pierwszym wywołaniu funkcji, sortowanie odbywa się od najmniejszej do największej wartości, przy drugim wywołaniu dla tego samego parametru, sortuje od największej do najmniejszej wartości, czyli odwrotnie niż do poprzedniego i tak na przemian dla każdego kolejnego.

Druga metoda zwraca sposób sortowania dla pola podanego w parametrze. Jeśli nie jest ono sortowane, funkcja zwraca pusty string.

A tak wyglądają nagłówki w szablonie:

<th (click)="sortingBy('number')">Numer 
    <i class="sort icon" [ngClass]="{'descending': (order('number')=='DESC'), 'ascending': (order('number')=='ASC')}"></i>
</th>

Efekt jest taki, że obok nagłówka kolumny w tabeli, pojawia się strzałka, zgodnie z kierunkiem sortowania. Tak wygląda to w praktyce:

ezgif-3-f6cda5e7d8

Kolejną rzeczą, którą udało mi się wykonać, jest obsługa checkboxów i usuwanie. W każdej tabeli każda pozycja ma swój checkbox, każda tabela ma również checkbox, który zaznacza wszystkie checkboxy w tabeli. Przez to, trzeba sprawdzać, czy wszystkie checkboxy zostały zaznaczone i zgodnie z tym zaznaczać, lub odznaczac głównego checkboxa.

Każdy element tabeli ma checkboxa, który wywołuje funkcję addDelete i sprawdza, czy dany numer id, jest wpisany do tablicy elementów do usunięcia:

<input type="checkbox" (change)="addDelete(document.id)" [checked]="isCheck(document.id)">

A tak wygląda metoda addDelete:

addDelete(id)
{
    if(this.delete.indexOf(id) == -1)
    {
        this.delete.push(id);
    }else{
        this.delete.splice(this.delete.indexOf(id), 1);
    }
}

Metoda indexOf, zwraca index podanego elementu z tablicy. Jeśli podany element nie występuje, zwraca -1. Funkcja addDelete sprawdza, czy dany numer id występuje w tablicy delete, jeśli nie, to go dodaje, jeśli tak, to usuwa ten element z tablicy.

Funkcja isCheck:

isCheck(id)
{
    if(this.delete.indexOf(id) == -1)
    {
        return false;
    }else{
        return true;
    }
}

Funkcja ta sprawdza, czy element o podanym id istnieje w tablicy delete. Jeśli tak, to zwraca true, jeśli nie, to false.

Tabela posiada również checkbox, do zaznaczenia wszystkich pozycji:

<input type="checkbox" (change)="allDelete()" [checked]="isAllChecked()">

Tak wygląda funkcja allDelete:

allDelete()
{
    if(!this.allDeleteChecked)
    {
        this.allDeleteChecked = true;
        for(let item in this.documents)
        {
            let id = this.documents[item].id;
            if(this.delete.indexOf(id) == -1)
            {
                this.delete.push(id);
            }
        }
    }else{
        this.allDeleteChecked = false;
        this.delete = [];
    }
}

Korzysta ona ze zmiennej allDeleteChecked, która przechowuje informację, o zaznaczenie checkboxa zaznaczającego wszystkie pozycje. Jeśli jest on zaznaczony, to odznacza go i czyści tablicę, jeśli natomiast jest zaznaczony, dodaje do niej id wszystkich dokumentów.

Ostatnia funkcja potrzebna do działania, to isAllCheck:

isAllChecked()
{
    let is = true;
    for(let item in this.documents)
    {
        let id = this.documents[item].id;
        if(this.delete.indexOf(id) == -1)
        {
            is = false;
            this.allDeleteChecked = false;
        }
    }
    if(this.delete.length<=0)
    {
        is = false;
    }
    if(is)
    {
            this.allDeleteChecked = true;
    }
    return is;
}

Funkcja ta porównuje tablicę elementów do usunięcia, z tablicą obiektów wszystkich dokumentów. Jeśli chociaż jeden z dokumentów nie będzie miał pary, funkcja zwraca false. Następnie, w przypadku, gdyby w tablicy documents nie było obiektów, to drugi if sprawdza, czy tablica delete jest większa od zera. Ostatni if ustawia zmienną allDeleteChecked na true, jeśli wszystkie dokumenty są zaznaczone.

Tutaj działanie tej funkcji:

ezgif-3-5d421e6306

Udało mi się również dodać od razu usuwanie dokumentów. Odpowiada za to funkcja deleteChecked:

deleteChecked()
{
    for(let id in this.delete)
    {
        this.sub = this.documentService.deleteDocument(this.delete[id])
            .subscribe((ok)=>{this.searchDocuments();});
    }
}

Pobiera ona elementy z tablicy delete i na każdym z nich wykonuje metodę deleteDocument z usługi document.service:

deleteDocument(id: number){
    let headers = new Headers({ 'Authorization': 'Bearer ' + this.authenticationService.token });
    let options = new RequestOptions({ headers: headers });

    return this.http.delete('http://localhost:8000/api/documents/'+id, options);
}

Tego chyba nie trzeba wyjaśniać.

Myślałem, że jest tego mniej, a jednak trochę się tego zebrało. Muszę teraz zająć się dopisanie do każdego kontrolera w API parametrów sortowania, ponieważ przydadzą się one w każdej tabeli. Muszę też przenieść jak największą ilość kodu z komponentu, do usług, żebym mógł bez problemu używać ich w każdym komponencie, bez zbędnego powielania kodu.

Pozdrawiam!
MTK

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑