W jaki sposób działa nawigacja w Blazorze?

Niewiele jest aplikacji składających się wyłącznie z jednej strony, więc temat nawigacji na pewno wcześniej czy później będzie dotyczyć również Ciebie. W tym wpisie postaram się przedstawić jak ustawić nawigacje między komponentami, przekazywać parametry przez url oraz w jaki sposób budować linki do nawigacji.

Każda aplikacja Blazor ma swój komponent startowy podany w Program.cs, najczęściej jest to App.razor.

builder.RootComponents.Add<App>("#app");

Łączy on tag z id app, który będzie miejscem wyświetlania aplikacji blazorowej z komponentem App. Natomiast komponent App składa się z szablonu routingu, który może wyglądać następująco:

<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

Opisuje on w jakim assembly znajdują się nasze komponenty poprzez atrybut AppAssembly. Jeżeli chcemy przechowywać komponenty w więcej niż 1 assembly możemy wykorzystać do tego atrybut AdditionalAssemblies. Gdy komponent zostanie odnaleziony to zostaje on renderowany z kontekstem routeData, który zawiera dane dotyczące wybranej ścieżki routingu. Dodatkowo możemy podać domyślny layout w atrybucie DefaultLayout, który ma być użyty na komponencie.

W przypadku, gdy nie zostanie znaleziony żaden komponent na stronie zostanie wyświetlona sekcja NotFound. W tym wypadku również możesz przekazać RouteView, jeżeli masz przygotowany bardziej złożony komponent.

Umiemy już ustawić szablon routingu, tylko jak przypisać komponenty pod poszczególne ścieżki? Służy do tego dyrektywa @page. Przykładowy komponent:

@page "/products/{Id}"

@inject IProductService productService 

<PageTitle>Product - @product?.Name</PageTitle>

<div>Name - @product?.Name</div>

@code {
    [Parameter]
    public string Id { get; set; }

    private Product product { get; set; }

    protected override async Task OnInitializedAsync()
    {
        product = productService.GetById(Id);
    }
}

W komponencie użyliśmy dyrektywy @page wraz z podaniem ścieżki /products/{Id}. Oznacza ona, że do naszego komponentu będzie można odwołać się po podaniu ścieżki bazowej z /products/{Id}, zakładając, że używasz lokalnego środowiska taka ścieżka może wyglądać następująco:

https://localhost:8000/products/1

Jeżeli nie możesz się dostać do podanej ścieżki to najprawdopodobniej twoja aplikacja używa innego portu, sprawdź go w pliku launchSettings.json.

Domyślnie wszystkie parametry routingu będą reprezentowały typ string, więc gdybyśmy chcieli zmienić Id na int to nawigacja do naszego komponentu przestała by działać. Aby wymusić konwertowanie parametru na konkretny typ należy podać go po nazwie w ścieżce routingu. W naszym wypadku należy podać /products/{Id:int}. Wymuszenie typu ograniczone jest wyłącznie do typów prostych oraz guid i datetime. Natomiast, gdy chcemy uzyskać parametr opcjonalny możemy podać znak ? na końcu, na przykład /products/{Id?}. Jest jeszcze opcja zebrania wszystkich znaków występujących od określonego miejsca w ścieżce do jednego parametru przy pomocy znaku *. Wygląda to następująco /products/{Id}/{*productQuery}.

Teraz możemy już budować komponenty do których będzie można nawigować w naszej aplikacji. Pozostaje jeszcze stworzyć odnośniki, możemy to zrobić bezpośrednio przy pomocy tagów <a> z podaniem ścieżki, mamy też do dyspozycji wbudowany komponent NavLink, który ma kilka dodatkowych możliwości. Użycie NavLink jest następujące:

<nav>
   <NavLink href="products" ActiveClass="active">Products</NavLink>
   <NavLink href="categories" ActiveClass="active">Categories</NavLink>
   <NavLink href="customers" ActiveClass="active">Customers</NavLink>
</nav>

Podobnie jak w tagu <a> ścieżkę do której użytkownik ma zostać przeniesiony podajemy w atrybucie href, dodatkowo w sytuacji w której link jest aktywny, możemy ustawić dodatkowe klasy css w atrybucie ActiveClass. Domyślnie za aktywny link uznajemy taki, który zawiera się w pełnym adresie do strony. Przykładowo products zawiera się w adresie https://localhost:8000/products, pozostaje jeszcze przypadek, gdy mamy kilka adresów, które mogłyby kolidować. Gdybyśmy ustawili linki do products i products/1 to link do products byłby aktywny w obu przypadkach. Aby to rozwiązać należy ustawić atrybut Match na NavLinkMatch.All.

Występuje jeszcze jedna sytuacja w której może zdarzyć się nam potrzeba nawigacji do innych komponentów. Jest to nawigacja bezpośrednio w kodzie, na przykład, gdy użytkownik zaloguje się do aplikacji, chcemy przenieść go automatycznie do części wyłącznie dla zalogowanych. Aby to zrobić należy wstrzyknąć serwis NavigationManager i użyć na nim metody NavigateTo. Przykładowe wykorzystanie:

@page "/products/{Id}"

@inject ProductService productService
@inject NavigationManager navigationManager

<div>
    <div>Name - @product?.Name</div>
    <div>
        <button @onclick="DeleteProduct">Delete</button>
    </div>
</div>

@code {
    [Parameter]
    public string Id { get; set; }

    private Product product { get; set; }

    protected override async Task OnInitializedAsync()
    {
        product = productService.GetById(Id);
    }

    private async Task DeleteProduct()
    {
        await productService.DeleteAsync(product?.Id);
        navigationManager.NavigateTo("products");
    }
}

W tym przykładzie po usunięciu produktu w metodzie DeleteProduct następuje przekierowanie do strony z produktami. Dodatkowo nasz komponent może podłączyć się do eventu informującego o zmianach lokalizacji o nazwie LocationChanged.

Teraz jesteś już w pełni gotowy, aby stworzyć aplikacje w której będzie nawigacja między komponentami. Jeżeli interesują Cię bardziej zaawansowane tematy to zachęcam do zapoznania się z metodą OnNavigateAsync oraz tagiem <Navigating>, dzięki którym będziesz mógł decydować o tym czy zezwolić na przekierowanie, a także jak wyświetlić informacje o ładowaniu strony.

Jeżeli uznasz ten post za przydatny to proszę udostępnij go innym, natomiast jak chcesz być na bieżąco i otrzymywać informacje o moich aktywnościach przed innymi to zapraszam Cię do newslettera na którym regularnie udostępniam przedpremierowo artykuły, materiały wideo i wiele więcej.

Share via
Copy link
Powered by Social Snap