Hierarchia danych jest wszechobecna w aplikacjach biznesowych – katalog produktów, struktura organizacyjna firmy oraz zarządzanie projektami lub zadaniami często wymagają reprezentacji wielopoziomowej. Użytkownicy aplikacji potrzebują narzędzi pozwalających na przejrzyste i intuicyjne poruszanie się po zagnieżdżonych strukturach. Prezentacja danych w formie czytelnego, wielopoziomowego, hierarchicznego widoku jest jednym z większych wyzwań, z którymi mierzą się twórcy aplikacji Canvas Apps.
Użytkownicy końcowi oczekują funkcjonalnych i intuicyjnych interfejsów, które umożliwiają szybkie zrozumienie i nawigację po danych. Prezentacja informacji w formie wielopoziomowej listy może znacznie poprawić czytelność i efektywność pracy. Hierarchia pozwala użytkownikowi lepiej zrozumieć kontekst, zależności oraz stopień szczegółowości. Niestety, Canvas Apps, pomimo mnogości gotowych komponentów, nie oferuje gotowego rozwiązania do elastycznej wizualizacji danych w takiej formie.
Powstaje zatem potrzeba tworzenia własnych rozwiązań, o których więcej dowiecie się z tego artykułu.
Metody wizualizacji danych w postaci hierarchii
Najpopularniejszą metodą wizualizacji danych w postaci hierarchii jest wykorzystanie zagnieżdżonych galerii. Jest to stosunkowo łatwe w implementacji rozwiązanie, które umożliwia prezentację 2-poziomowej struktury danych.
Przykład wykorzystania:
Główna galeria pokazuje działy, a w każdym jej rekordzie znajduje się podrzędna galeria z pracownikami danego działu.

Źródło danych galerii zagnieżdżonej:

Uzależniając widoczność zagnieżdżonych galerii np. od wartości rekordu nadrzędnego (grupy), która aktualizowana jest po naciśnięciu ikonki, można również w stosunkowo łatwy sposób wdrożyć rozwijane/zwijane sekcje.

Widoczność galerii zagnieżdżonej:

Akcja na zaznaczeniu ikonki:

Rodzaj ikonki:

Z uwagi na niski poziom skomplikowania tego rozwiązania, jest ono bardzo popularne i często wykorzystywane. W przypadku dwupoziomowej struktury hierarchii oraz optymalnej ilości danych, zastosowanie tego typu wizualizacji może być dobrym rozwiązaniem.
Wady rozwiązania
Trzeba jednak pamiętać, że wiąże się z pewnymi ograniczeniami oraz problemami, głównie objawiającymi się w postaci niskiej efektywności oraz braku elastyczności. Wewnętrzna galeria ładuje dane osobno, co znacząco wpływa na wydajność i szybkość działania systemu. Próba stworzenia dodatkowego poziomu zagnieżdżenia danych wyłącznie spotęguje ten efekt i jeszcze bardziej spowolni aplikację.
Kolejnym, choć tym razem mniej oczywistym minusem tego rozwiązania jest limit wysokości pojedynczego rekordu galerii. Z uwagi na to, że każda z zagnieżdżonych galerii wchodzi w skład rekordów galerii nadrzędnej, obowiązuje ją limit wysokości wynoszący 5000. Należy o tym pamiętać, szczególnie w przypadku wyświetlania większej ilości rekordów z danymi.
Widok hierarchiczny w jednej galerii
Rozwiązaniem, które obchodzi większość z powyżej wymienionych ograniczeń i problemów, może być implementacja widoku hierarchicznego w jednej galerii przy wykorzystaniu klucza umożliwiającego dynamiczne filtrowanie i układanie danych w wielopoziomowej strukturze.
Definiowanie kluczy
Najważniejszym elementem tworzenia tego typu widoku jest poprawne skonstruowanie klucza, na podstawie którego będzie odbywać się sortowanie danych w galerii. Pomocne może się okazać również zdefiniowanie stopnia zagnieżdżenia rekordów z danymi w kontekście całej wielopoziomowej struktury. Do budowy klucza najlepiej użyć unikalnych informacji w ramach konkretnej instancji danych. Najlepszym wyborem może okazać się GUID, ponieważ oprócz unikalności ma dodatkową zaletę, która w tym przypadku jest bardzo pomocna – stała ilość znaków.
Zdefiniowanie kluczy dla poszczególnych rekordów może odbyć się na kilka sposobów.
Jednym z nich jest użycie pętli, która będzie obracać się do momentu zakończenia przetwarzania wszystkich rekordów. Ponieważ w Canvas Apps nie ma wbudowanej funkcji podobnej do tych z popularnych języków programowania (np. ‘do until’ lub ‘while’ ), to obejściem tego może być wykorzystanie samowyzwalającej się kontrolki ‘toggle’. To sztuczka, która może znaleźć zastosowanie nie tylko w tej sytuacji, ale także w każdej innej, gdy chcielibyśmy wykorzystać logikę działania pętli wykonującej się do momentu spełnienia określonego warunku.
Przykład:
W tabeli zadań istnieją relacje pomiędzy rekordami danych z tej samej tabeli. Twórcy zadań mogą zdefiniować w ten sposób kolejność ich wykonania, podzielić je na konkretne etapy realizacji, pogrupować itd. Każdy z rekordów posiada unikalny identyfikator (GUID) zapisany w kolumnie ‘InternalId’ . W kolumnie ‘ParentInternalId’ opcjonalnie zdefiniowany może być również identyfikator zadania nadrzędnego tzw. rodzica.
To przykład, którego charakterystyka relacji między danymi znajduje odzwierciedlenie w wielu instancjach danych i przypadkach biznesowych.

Z uwagi na brak zdefiniowanej konkretnej liczby poziomów zagnieżdżenia danych oraz ilości rekordów znajdujących się na tych poziomach, do generacji klucza wykorzystamy kontrolkę ‘toggle’. W celu implementacji łatwej i kontrolowanej akcji wyzwolenia działania kodu można wykorzystać zmienną, którą należy podstawić do wartości domyślnej toggla i w odpowiednim dla nas miejscu (np. ‘OnVisible’ ekranu) zdefiniować jej wartość na ‘true’ (wywołanie), a następnie na ‘false’ (dezaktywacja i oczekiwanie na kolejne wywołanie).
Deklaracja wartości zmiennej:

Wartość domyślna toggla:

Kod, który ma się wykonać w trakcie działania toggla, należy zdefiniować we właściwości ‘OnCheck’ kontrolki. Idea jest taka, aby zaktualizować wartości w kolumnach z kluczem i poziomem zagnieżdżenia dla każdego rekordu.
Sekwencja aktualizacji wartości następować będzie od najwyższego poziomu (pozycji bez zdefiniowanego rodzica), w dół (pozycji najbardziej zagnieżdżonych). W tym celu przy każdym obrocie pętli tworzona jest kolekcja z danymi podlegającymi aktualizacji. Liczba obrotów pętli (wywołań kodu toggla) jest równa liczbie poziomów zagnieżdżenia danych w całej strukturze hierarchii. Po tym następuje aktualizacja wartości klucza oraz poziomu zagnieżdżenia.
Wartość klucza tworzona jest z identyfikatorów rekordów nadrzędnych, procesowanego rekordu oraz opcjonalnie z wartości umożliwiającej wdrożenie dodatkowego sortowania (w tym przypadku data rozpoczęcia). Wartość poziomu zagnieżdżenia to wartość liczbowa, gdzie 0 oznacza rekord niezagnieżdżony. Wzrost tych wartości oznacza większy stopień zagnieżdżenia danych.
Na końcu sprawdzane jest, czy nadal istnieją nieprzeprocesowane dane i w przypadku otrzymania odpowiedzi twierdzącej następuje ponowna aktywacja toggla. Wartość negatywna tego warunku oznacza koniec wykonywania się kodu.
Kod na aktywacji toggla:

Opcjonalnie, w przypadku gdy istotna jest kolejność wyświetlanych rekordów w obrębie tej samej instancji (te sam poziom + ten sam rodzic), w trakcie definiowania klucza, można uwzględnić wartość kolumny, po której ma nastąpić sortowanie.
Należy jednak pamiętać, że docelowe sortowanie, które zostanie wdrożone w galerii, jest sortowaniem alfabetycznym. Ma to szczególne znaczenie, gdy oczekujemy sortowania po kolumnie z wartościami liczbowymi lub datami. W przypadku dat dobrym rozwiązaniem jest uwzględnienie odpowiedniego formatu (np. ‘yyyy-mm-dd’) – tak jak w przykładzie powyżej.
Dane liczbowe mogą okazać się bardziej problematyczne, jednak dla tego typu informacji również można stworzyć rozwiązanie, które zadziała. Należy jedynie oszacować prognozowaną, maksymalną liczbę znaków największych wartości. W przykładzie poniżej jest to 3 (czyli maksymalna szacowana wartość to 999). Dla zachowania buforu bezpieczeństwa można zwiększyć tę wartość o margines błędu szacunkowego.

W źródle danych galerii należy odnieść się do przygotowanej kolekcji oraz uwzględnić sortowanie alfabetyczne po kolumnie z kluczem.

Aby zobrazować poziomy zagnieżdżenia rekordów w galerii, można np. wykorzystać wartość z kolumny ‘LevelInHierarchy’ i uzależnić od tego odsunięcie tekstu oraz kolor tła.

Odsunięcie tekstu:

Kolor wypełnienia tła:


Podsumowanie
Powyższe rozwiązanie umożliwia wizualizację wielopoziomowej hierarchii danych bez konieczności wcześniejszego określania ilości poziomów. Ze względu na elastyczność może znaleźć szerokie zastosowanie w wielu scenariuszach. Rozwiązanie nie wyklucza również opcji implementacji rozwijanych sekcji oraz filtrów.
Należy jednak pamiętać, aby zadbać o intuicyjne rozróżnienie poszczególnych instancji danych, tak by poszczególne struktury hierarchiczne nie łączyły się losowo w widoku. Jest to jednak aspekt wizualny, który można obsłużyć na wiele sposobów, w zależności od preferencji.
Zostaw komentarz