Navigation
There are 3 kinds of managed navigation in applications using Hydro:
- Navigation via links.
- Navigation initiated in components (without page reload).
- Navigation initiated in components (with full page reload).
Navigation via links
With hydro-link
attribute relative links in your application can be loaded in the background and applied to the current document instead of doing the full page reload.
Examples:
Attribute applied directly on a link:
<a href="/page" hydro-link>My page</a>
<a href="/page" hydro-link>My page</a>
Attribute applied directly on a parent of the links:
<ul hydro-link>
<li><a href="/page1">My page 1</a></li>
<li><a href="/page2">My page 2</a></li>
</ul>
<ul hydro-link>
<li><a href="/page1">My page 1</a></li>
<li><a href="/page2">My page 2</a></li>
</ul>
Navigation initiated in components (without page reload)
Let's take a look at he following code:
// MyPage.cshtml.cs
public class MyPage : HydroComponent
{
public void About()
{
Location(Url.Page("/About/Index"));
}
}
// MyPage.cshtml.cs
public class MyPage : HydroComponent
{
public void About()
{
Location(Url.Page("/About/Index"));
}
}
Choosing the target selector during navigation
Often when navigating to another page, the only part of the page that is changing is the content section, while layout remains the same. In those cases we can disable layout rendering, send only the content section, and instruct Hydro where to put it. It can be achieved by using HydroTarget
:
// Layout.cshtml
<html>
<head>
<meta name="hydro-config" />
<title>Test</title>
<script defer src="~/hydro/hydro.js" asp-append-version="true"></script>
<script defer src="~/hydro/alpine.js" asp-append-version="true"></script>
</head>
<body>
<ul hydro-link>
<a href="/">Home</a>
<a href="/products">Product</a>
</ul>
<div id="content">
@RenderBody()
</div>
</body>
</html>
// Layout.cshtml
<html>
<head>
<meta name="hydro-config" />
<title>Test</title>
<script defer src="~/hydro/hydro.js" asp-append-version="true"></script>
<script defer src="~/hydro/alpine.js" asp-append-version="true"></script>
</head>
<body>
<ul hydro-link>
<a href="/">Home</a>
<a href="/products">Product</a>
</ul>
<div id="content">
@RenderBody()
</div>
</body>
</html>
// Index.cshtml
@{
if (HttpContext.IsHydro())
{
Layout = null;
this.HydroTarget("#content");
}
}
Content of the page
// Index.cshtml
@{
if (HttpContext.IsHydro())
{
Layout = null;
this.HydroTarget("#content");
}
}
Content of the page
We are using here #content
as the target, but it's also possible to use Hydro's predefined identifier #hydro
, example:
<div id="@HydroComponent.LocationTargetId">
@RenderBody()
</div>
or
<div id="hydro">
@RenderBody()
</div>
<div id="@HydroComponent.LocationTargetId">
@RenderBody()
</div>
or
<div id="hydro">
@RenderBody()
</div>
this.HydroTarget(); // selector will be set to #hydro
this.HydroTarget(); // selector will be set to #hydro
HydroTarget
has also an optional parameter title
, which is used to set the title of loaded page. Example:
// Index.cshtml
@{
if (HttpContext.IsHydro())
{
Layout = null;
this.HydroTarget(title: "Home");
}
}
Content of the page
// Index.cshtml
@{
if (HttpContext.IsHydro())
{
Layout = null;
this.HydroTarget(title: "Home");
}
}
Content of the page
Passing the payload
Sometimes it's needed to pass a payload object from one page to another. For such cases, there is a second optional parameter called payload
:
// Products.cshtml.cs
public class Products : HydroComponent
{
public HashSet<string> SelectedProductsIds { get; set; }
// ... product page logic
public void AddToCart()
{
Location(Url.Page("/Cart/Index"), new CartPayload(SelectedProductsIds));
}
}
// Products.cshtml.cs
public class Products : HydroComponent
{
public HashSet<string> SelectedProductsIds { get; set; }
// ... product page logic
public void AddToCart()
{
Location(Url.Page("/Cart/Index"), new CartPayload(SelectedProductsIds));
}
}
// CartPayload.cs
public record CartPayload(HashSet<string> ProductsIds);
// CartPayload.cs
public record CartPayload(HashSet<string> ProductsIds);
Reading the payload
Use the following method to read the previously passed payload:
// CartSummary.cshtml.cs
public class CartSummary : HydroComponent
{
public CartPayload Payload { get; set; }
public override void Mount()
{
Payload = GetPayload<CartPayload>();
}
// ...
}
// CartSummary.cshtml.cs
public class CartSummary : HydroComponent
{
public CartPayload Payload { get; set; }
public override void Mount()
{
Payload = GetPayload<CartPayload>();
}
// ...
}
Navigation initiated in components (with full page reload)
If full page reload is needed, use the Redirect
method:
// MyPage.cshtml.cs
public class MyPage : HydroComponent
{
public void Logout()
{
// logout logic
Redirect(Url.Page("/Home/Index"));
}
}
// MyPage.cshtml.cs
public class MyPage : HydroComponent
{
public void Logout()
{
// logout logic
Redirect(Url.Page("/Home/Index"));
}
}