### Install Hydro Package Source: https://github.com/hydrostack/hydro/blob/main/README.md Install the Hydro package using the .NET CLI for ASP.NET Core projects. ```console dotnet add package Hydro ``` -------------------------------- ### Sample Program.cs with Hydro Integration Source: https://github.com/hydrostack/hydro/blob/main/docs/content/introduction/getting-started.md An example of a `Program.cs` file demonstrating the integration of Hydro services and middleware within an ASP.NET Core application. ```csharp using Hydro.Configuration; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); builder.Services.AddHydro(); // Hydro var app = builder.Build(); app.UseStaticFiles(); app.UseRouting(); app.MapRazorPages(); app.UseHydro(); // Hydro app.Run(); ``` -------------------------------- ### Basic Hydro View Implementation Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Implement the HTML structure for a Hydro view. This example shows a simple submit button. ```razor @model Submit ``` -------------------------------- ### VitePress Custom Container Examples Source: https://github.com/hydrostack/hydro/blob/main/docs/content/markdown-examples.md Shows the markdown syntax for creating custom info, tip, warning, danger, and details containers in VitePress. ```md ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: danger This is a dangerous warning. ::: ::: details This is a details block. ::: ``` -------------------------------- ### Usage Example: Passing a Lambda as a Click Handler Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Example of how to use the `FormButton` view by passing a lambda expression to the `click` attribute. ```razor Save ``` -------------------------------- ### Action with Integer Parameter Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md Actions can accept parameters. This example shows a `Set` action that takes an integer to update the `Count` property. ```csharp public class Counter : HydroComponent { public int Count { get; set; } public void Set(int newValue) { Count = newValue; } } ``` -------------------------------- ### Hydro Action Loading Indicator Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/ui-utils.md This CSS and Razor example demonstrates how to show a loading indicator within a button when a Hydro operation is in progress, using the `.hydro-request` class. ```css /* MyComponent.cshtml.css */ .loader { display: none; } .hydro-request .loader { display: inline-block; } ``` ```razor @model MyComponent ``` -------------------------------- ### Hydro View Parameter Implementation Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Implement the HTML structure for a Hydro view that uses parameters. This example displays a message within an alert div. ```razor @model Alert
@Model.Message
``` -------------------------------- ### Using a Hydro View Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Integrate a defined Hydro view into another Razor view by using its tag-like syntax. This example uses the `Submit` view. ```razor ``` -------------------------------- ### Razor Form with Validation and Binding Source: https://github.com/hydrostack/hydro/blob/main/docs/content/index.md Shows a complete form example in Razor Pages using Hydro. It includes input binding (`bind`), validation (`asp-validation-for`), and form submission handling (`on:submit`). ```razor @model NameForm
@if (Model.Message != null) {
@Model.Message
}
``` ```csharp // NameForm.cs public class NameForm : HydroComponent { [Required, MaxLength(50)] public string Name { get; set; } public string Message { get; set; } public void Save() { if (!Validate()) { return; } Message = "Success!"; Name = ""; } } ``` -------------------------------- ### Define a Hydro Component (C# Class) Source: https://github.com/hydrostack/hydro/blob/main/README.md Define the server-side logic for a Hydro component by creating a C# class that inherits from `HydroComponent`. This example implements the `Add` method for the counter. ```csharp // Counter.cs public class Counter : HydroComponent { public int Count { get; set; } public void Add() { Count++; } } ``` -------------------------------- ### Define a Hydro Component (Razor View) Source: https://github.com/hydrostack/hydro/blob/main/README.md Define the UI for a Hydro component using a Razor view (`.cshtml` file). This example shows a simple counter component. ```razor @model Counter
Count: @Model.Count
``` -------------------------------- ### Usage: Passing Dynamic HTML Attributes to a Hydro View Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Example of using the `Alert` view and passing an additional `class` attribute that will be rendered dynamically. ```razor ``` -------------------------------- ### Configure Long Polling with Custom Interval Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/long-polling.md Decorate a parameterless action with the [Poll] attribute and set the Interval property to customize the polling frequency in milliseconds. This example polls every 60 seconds. ```csharp public class NotificationsIndicator(INotifications notifications) : HydroComponent { public int NotificationsCount { get; set; } [Poll(Interval = 60_000)] public async Task Refresh() { NotificationsCount = await notifications.GetCount(); } } ``` -------------------------------- ### Razor Input Binding Example Source: https://github.com/hydrostack/hydro/blob/main/docs/content/index.md Demonstrates how to bind an input element to a model property in Razor Pages using Hydro's `bind:keydown` directive. This updates the model as the user types. ```razor @model NameForm
Hello @Model.Name
``` ```csharp // NameForm.cs public class NameForm : HydroComponent { public string Name { get; set; } } ``` -------------------------------- ### Binding Action with JavaScript Parameter Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md This Razor example shows how to bind a button click to an action that accepts a parameter evaluated by JavaScript. `window.myInput.value` is executed client-side, and its result is passed to the `Update` action. ```razor @model Content
``` -------------------------------- ### Create ASP.NET Core Web App Source: https://github.com/hydrostack/hydro/blob/main/README.md Create a new ASP.NET Core web application using the .NET CLI. ```console dotnet new webapp -o MyApp cd MyApp ``` -------------------------------- ### Configure Hydro Services and Middleware Source: https://github.com/hydrostack/hydro/blob/main/README.md Add Hydro services to the dependency injection container and configure its middleware in the application's startup code. ```csharp builder.Services.AddHydro(); ... app.UseHydro(builder.Environment); ``` -------------------------------- ### Configure Hydro Services and Middleware Source: https://github.com/hydrostack/hydro/blob/main/docs/content/introduction/getting-started.md Register Hydro services and middleware in your application's startup code. Ensure `UseHydro` is called after `UseStaticFiles` and `UseRouting`. ```csharp builder.Services.AddHydro(); ``` ```csharp app.UseHydro(); ``` -------------------------------- ### JavaScript Syntax Highlighting with Line Highlight Source: https://github.com/hydrostack/hydro/blob/main/docs/content/markdown-examples.md Demonstrates JavaScript code with a specific line highlighted using Shiki syntax highlighting. ```js export default { data () { return { msg: 'Highlighted!' } } } ``` -------------------------------- ### Create a Hydro Component's View Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/components.md Create the UI for a Hydro component using a .cshtml file. The component's class should be set as the view model. Ensure a single root element and use `Model` to access component state. ```razor @model PageCounter
Count: @Model.Count
``` -------------------------------- ### Listen for Hydro Component Initialization Event Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/js.md Attach an event listener to the document to catch the 'HydroComponentInit' event, which is triggered after a component is initialized. The event detail contains information about the initialized component. ```javascript document.addEventListener('HydroComponentInit', function (e) { console.log('Component initialized', e.detail); }); ``` -------------------------------- ### Render Component with Available Parameters Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Demonstrates how to render a component when certain properties are marked as not bound. Only the bound properties (like 'name') will be available for passing values. ```razor @* Ok *@@ @* Currencies won't be passed *@ ``` -------------------------------- ### Hydro Component Lifecycle and Event Handling Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/components.md Implement component lifecycle methods like `MountAsync` and `Render`, and handle custom events by subscribing in the constructor. Services can be injected via dependency injection. ```csharp public class EditUserForm : HydroComponent { private readonly IDatabase _database; public EditUserForm(IDatabase database) { _database = database; Subscribe(Handle); } public string UserId { get; set; } [Required] public string Name { get; set; } public override async Task MountAsync() { var formData = ...; // fetch data from database Name = formData.Name; } public override void Render() { ViewBag.IsLongName = Name.Length > 20; } public async Task Save() { await _database.UpdateUser(UserId, Name); // save the data } public void Handle(SystemMessageEvent message) { Message = message.Text; } } ``` -------------------------------- ### Handle Multiple Files Upload in Component Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Adapt the component to handle multiple files by changing the property type to an array (`IFormFile[]`) and iterating through the uploaded files in `BindAsync`. Each file is processed and its temporary ID is stored. ```csharp // AddAttachment.cshtml.cs public class AddAttachment : HydroComponent { [Transient] public IFormFile[] DocumentFiles { get; set; } [Required] public List DocumentIds { get; set; } public override async Task BindAsync(PropertyPath property, object value) { if (property.Name == nameof(DocumentFiles)) { DocumentIds = []; var files = (IFormFile[])value; foreach (var file in files) { DocumentIds.Add(await GetStoredTempFileId(file)); } } } // rest of the file same as in the previous example } ``` -------------------------------- ### Implement Caching for Customer Data Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md This C# code demonstrates how to use the `Cache` method to create a cached property for fetching customer data. It includes logic for filtering based on a search phrase and accessing the cached value. ```csharp // CustomerList.cshtml.cs public class CustomerList(IDatabase database) : HydroComponent { public string SearchPhrase { get; set; } public HashSet Selection { get; set; } = new(); public Cache>> Customers => Cache(async () => { var query = database.Query(); if (!string.IsNullOrWhiteSpace(SearchPhrase)) { query = query.Where(p => p.Name.Contains(SearchPhrase)); } return await query.ToListAsync(); }); public async Task Print() { var customers = await Customers.Value; if (!customers.Any()) { return; } var customerIds = customers.Select(c => c.Id).ToList(); Location(Url.Page("/Customers/Print"), new CustomersPrintPayload(customerIds)); } } ``` -------------------------------- ### Include Hydro JavaScript Files Source: https://github.com/hydrostack/hydro/blob/main/README.md Add Hydro and Alpine.js script references to the head section of your layout file for client-side functionality. ```html ``` -------------------------------- ### Hydro View with Parameters Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define a Hydro view that accepts parameters. The `Message` property is exposed and can be passed from the parent view. ```csharp public class Alert : HydroView { public string Message { get; set; } } ``` -------------------------------- ### Read and Write String Cookies Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/cookies.md Use CookieStorage.Get to read a cookie with a default value and CookieStorage.Set to write a cookie. ```csharp // ThemeSwitcher.cshtml.cs public class ThemeSwitcher : HydroComponent { public string Theme { get; set; } public override void Mount() { Theme = CookieStorage.Get("theme", defaultValue: "light"); } public void Switch(string theme) { Theme = theme; CookieStorage.Set("theme", theme); } } ``` -------------------------------- ### Returning ComponentResults.File Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md The `ComponentResults.File` result allows an action to return a file from the server. Specify the file path and media type. ```csharp // ShowInvoice.cshtml.cs public class ShowInvoice : HydroComponent { public IComponentResult Download() { return ComponentResults.File("./storage/file.pdf", MediaTypeNames.Application.Pdf); } } ``` -------------------------------- ### Define a Parent Hydro Component with an Action Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define a `Parent` Hydro component with a `LoadText` method that can be called from a child view. ```csharp public class Parent : HydroComponent { public string Value { get; set; } public void LoadText(string value) { Value = value; } } ``` -------------------------------- ### Subscribe to an Event for Re-rendering Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Use this when you only need to re-render a component when a specific event occurs. No explicit handler is needed. ```csharp // ProductList.cshtml.cs public class ProductList : HydroComponent { public ProductList() { Subscribe(); } public override void Render() { // When ProductAddedEvent occurs, component will be rerendered } } ``` -------------------------------- ### Force Re-render with Key Parameter Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Demonstrates how to use the 'key' parameter to force a re-render of a component when its associated data changes. The key should be a unique identifier for the data, such as a hash code. ```razor ``` -------------------------------- ### Define a Hydro Component's Code-Behind Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/components.md Define the logic and state for a Hydro component by inheriting from `HydroComponent`. Use properties to hold state and methods to handle actions. ```csharp // ~/Pages/Components/PageCounter.cshtml.cs public class PageCounter : HydroComponent { public int Count { get; set; } public void Add() { Count++; } } ``` -------------------------------- ### Render Component with Key Argument Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Shows how to provide an optional 'key' argument when rendering a Hydro component. This is used to distinguish between multiple components of the same type during DOM updates. ```razor ``` ```razor ``` -------------------------------- ### Use Key for Multiple Components of Same Type Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Illustrates using the 'key' parameter within a loop to assign unique keys to multiple instances of the same component type, enabling proper DOM updates. ```razor @foreach (var item in Items) { } ``` ```razor ``` -------------------------------- ### Initiate Navigation from Component (No Reload) Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/navigation.md Call the `Location` method within a Hydro component to navigate to a new page without a full page reload. Ensure the target URL is correctly specified. ```csharp // MyPage.cshtml.cs public class MyPage : HydroComponent { public void About() { Location(Url.Page("/About/Index")); } } ``` -------------------------------- ### Returning ComponentResults.Challenge Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md Use `ComponentResults.Challenge` to initiate an authentication challenge, typically for external providers like GitHub. Authentication properties and schemes can be specified. ```csharp // Profile.cshtml.cs public class Profile : HydroComponent { public IComponentResult LoginWithGitHub() { var properties = new AuthenticationProperties { RedirectUri = RedirectUri, IsPersistent = true }; return ComponentResults.Challenge(properties, [GitHubAuthenticationDefaults.AuthenticationScheme]); } } ``` -------------------------------- ### Basic Hydro View Definition Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define a basic Hydro view by inheriting from the `HydroView` class. This sets up the component for use within Hydro. ```csharp public class Submit : HydroView; ``` -------------------------------- ### Configure Hydro for Targeted Content Updates Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/navigation.md In your layout file, include Hydro's configuration and scripts. In your page, conditionally set `Layout = null` and use `HydroTarget` to specify where the new content should be injected, preventing a full page reload. ```razor // Layout.cshtml Test
@RenderBody()
``` ```razor // Index.cshtml @{ if (HttpContext.IsHydro()) { Layout = null; this.HydroTarget("#content"); } } Content of the page ``` -------------------------------- ### Enable Anti-forgery Token in Hydro Configuration Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/xsrf-token.md Enable the anti-forgery token feature by setting `AntiforgeryTokenEnabled` to `true` in your Hydro service configuration. This is a crucial step for preventing XSRF attacks. ```csharp services.AddHydro(options => { options.AntiforgeryTokenEnabled = true; }); ``` -------------------------------- ### Render Hydro Component using Extension Method Source: https://github.com/hydrostack/hydro/blob/main/README.md Render a Hydro component in a Razor Page by calling the `Html.Hydro` extension method. ```razor ... @await Html.Hydro("Counter") ... ``` -------------------------------- ### Define a Simple Action Method Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md Define a C# method in your Hydro component class to be used as an action. This method will be invoked when a corresponding browser event occurs. ```csharp public class Counter : HydroComponent { public int Count { get; set; } public void Add() { Count++; } } ``` -------------------------------- ### Handle Single File Upload in Component Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Process a single uploaded file in the `BindAsync` method. The `[Transient]` attribute prevents the file from being serialized and sent back to the server unnecessarily. Files are stored temporarily. ```csharp // AddAttachment.cshtml.cs public class AddAttachment : HydroComponent { [Transient] public IFormFile DocumentFile { get; set; } [Required] public string DocumentId { get; set; } public async Task Save() { if (!Validate()) { return; } var tempFilePath = GetTempFileLocation(DocumentId); // Move your file at tempFilePath to the final storage // and save that information in your domain } public override async Task BindAsync(PropertyPath property, object value) { if (property.Name == nameof(DocumentFile)) { // assign the temp file name to the DocumentId DocumentId = await GetStoredTempFileId((IFormFile)value); } } private static async Task GetStoredTempFileId(IFormFile file) { if (file == null) { return null; } var tempFileName = Guid.NewGuid().ToString("N"); var tempFilePath = GetTempFileLocation(tempFileName); await using var readStream = file.OpenReadStream(); await using var writeStream = File.OpenWrite(tempFilePath); await readStream.CopyToAsync(writeStream); return tempFileName; } private static string GetTempFileLocation(string fileName) => Path.Combine(Path.GetTempPath(), fileName); } ``` -------------------------------- ### Define a Hydro View with an Event Handler Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define a `FormButton` Hydro view that accepts a click handler via the `Expression` type. ```csharp // FormButton.cshtml.cs public class FormButton : HydroView { public Expression Click { get; set; } } ``` -------------------------------- ### Hydro View Manual Naming Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define a Hydro view using manual naming with PascalCase and `nameof` to explicitly target the element name. This allows for direct mapping of class names to HTML tags. ```csharp [HtmlTargetElement(nameof(SubmitButton))] public class SubmitButton : HydroView; ``` -------------------------------- ### Razor Component for Click Actions Source: https://github.com/hydrostack/hydro/blob/main/docs/content/index.md Illustrates a simple counter component in Razor Pages using Hydro. It demonstrates how to handle click events (`on:click`) to call server-side methods and update the UI. ```razor @model Counter
Count: @Model.Count
``` ```csharp // Counter.cs public class Counter : HydroComponent { public int Count { get; set; } public void Add(int value) { Count += value; } } ``` -------------------------------- ### Define a Hydro View with a Message Property Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define an `Alert` Hydro view with a `Message` property and a dynamic `class` attribute. ```csharp // Alert.cshtml.cs public class Alert : HydroView { public string Message { get; set; } } ``` -------------------------------- ### Initiate Navigation with Full Page Reload Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/navigation.md Use the `Redirect` method within a Hydro component to perform a full page reload and navigate to a new URL. This is suitable for actions that require a complete refresh, such as logging out. ```csharp // MyPage.cshtml.cs public class MyPage : HydroComponent { public void Logout() { // logout logic Redirect(Url.Page("/Home/Index")); } } ``` -------------------------------- ### Global Event Dispatch in C# Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Publish events to all components in the application, regardless of their hierarchy. Use when multiple unrelated components need to be notified. ```csharp Dispatch(new ShowMessage(Content), Scope.Global); ``` ```csharp DispatchGlobal(new ShowMessage(Content)); ``` -------------------------------- ### Configure Data Protection Key Persistence with Entity Framework Core Source: https://github.com/hydrostack/hydro/blob/main/docs/content/advanced/load-balancing.md Use this configuration to persist data protection keys to a database using Entity Framework Core. This ensures keys are shared across all nodes in a load-balanced environment. ```csharp services.AddDataProtection() .PersistKeysToDbContext(); ``` -------------------------------- ### Binding Action with Integer Parameter Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md This Razor snippet demonstrates how to call an action method with an integer parameter using the `on:click` tag helper. ```razor @model Counter
Count: @Model.Count
``` -------------------------------- ### Parent Component Razor View Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Basic Razor view for the `Parent` component, including a placeholder for a child view. ```razor @model Parent ``` -------------------------------- ### Customize Cookie Options Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/cookies.md Pass a CookieOptions instance to CookieStorage.Set to further customize cookie settings like Secure. ```csharp CookieStorage.Set("theme", "light", encrypt: false, new CookieOptions { Secure = true }); ``` -------------------------------- ### Page Loading Indicator Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/ui-utils.md This CSS and HTML sets up a visual indicator for page loading using the `.hydro-loading` class. The animation `loadPage` defines the loading bar's behavior. ```html
``` -------------------------------- ### Bind Input Elements Using `bind` Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Use the `bind` attribute on input elements to synchronize their values with component properties. The `asp-for` tag helper is used here for convenience. ```razor ``` -------------------------------- ### Event and Expression Syntax Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md The `on` attribute follows the format `on:event="expression"`, where `event` is compatible with Alpine.js's `x-on` directive and `expression` is a C# lambda calling a callback method. ```razor ``` -------------------------------- ### Set Component Parameter using Dash-Case Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Set a component parameter using dash-case notation directly in the component tag. This is a common way to pass simple values. ```razor ``` -------------------------------- ### Asynchronous Event Dispatch in C# Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Use this for events that can be processed independently of the calling operation. This allows the UI to remain responsive. ```csharp public void Add() { Count++; Dispatch(new CountChangedEvent(Count), asynchronous: true); } ``` -------------------------------- ### Synchronous Event Dispatch in C# Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Use this for events that must complete before the calling operation finishes. The UI might remain unresponsive until the event is handled. ```csharp public void Add() { Count++; Dispatch(new CountChangedEvent(Count)); } ``` -------------------------------- ### Configure ASP.NET MVC Exception Handling Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/errors-handling.md This configuration sets up custom exception handling for ASP.NET MVC applications. It redirects non-Hydro requests and provides a JSON response with `UnhandledHydroError` for Hydro requests, customizing the error message. ```csharp app.UseExceptionHandler(b => b.Run(async context => { if (!context.IsHydro()) { context.Response.Redirect("/Error"); return; } var contextFeature = context.Features.Get(); switch (contextFeature?.Error) { // custom cases for custom exception types if needed default: context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; await context.Response.WriteAsJsonAsync(new UnhandledHydroError( Message: "There was a problem with this operation and it wasn't finished", Data: null )); return; } })); ``` -------------------------------- ### Render Hydro Component using Generic Tag Helper Source: https://github.com/hydrostack/hydro/blob/main/README.md Render a Hydro component in a Razor Page using the generic `hydro` tag helper and specifying the component's name. ```razor ... ... ``` -------------------------------- ### Custom Component Authorization Attribute Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/authorization.md Implement IHydroAuthorizationFilter to create a custom attribute that checks if the user is authenticated. If AuthorizeAsync returns false, the component will not be rendered. ```csharp public sealed class CustomComponentAuthorizeAttribute : Attribute, IHydroAuthorizationFilter { public Task AuthorizeAsync(HttpContext httpContext, object component) { var isAuthorized = httpContext.User.Identity?.IsAuthenticated ?? false; return Task.FromResult(isAuthorized); } } ``` ```csharp [CustomComponentAuthorize] public class ProductList : HydroComponent { } ``` -------------------------------- ### Hydro View Automatic Naming Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define a Hydro view using automatic naming conventions with dash-case notation. The class name `SubmitButton` will be used as ``. ```csharp public class SubmitButton : HydroView; ``` -------------------------------- ### Authorization Using Component State Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/authorization.md Create an attribute that uses component state for authorization. This involves defining an interface for the required state and using services like IAuthorizationService within the AuthorizeAsync method. ```csharp public interface IWorkspaceComponent { string WorkspaceId { get; } } ``` ```csharp public sealed class WorkspaceComponentAuthorizeAttribute : Attribute, IHydroAuthorizationFilter { public async Task AuthorizeAsync(HttpContext httpContext, object component) { var workspaceComponent = (IWorkspaceComponent)component; var authorizationService = httpContext.RequestServices.GetRequiredService(); return authorizationService.IsWorkspaceAuthorized(workspaceComponent.WorkspaceId); } } ``` ```csharp [WorkspaceComponentAuthorize] public class ProductList : HydroComponent, IWorkspaceComponent { public string WorkspaceId { get; set; } } ``` -------------------------------- ### Integrating Fluent Validation with Hydro Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/form-validation.md Attach Fluent Validation to your Hydro components by injecting an IValidator and using the provided Validate extension method. This allows for more sophisticated validation rules defined separately. ```csharp // Counter.cshtml.cs public class Counter(IValidator validator) : HydroComponent { public int Count { get; set; } public void Add() { if (!this.Validate(validator)) { return; } Count++; } public class Validator : AbstractValidator { public Validator() { RuleFor(c => c.Count).LessThan(5); } } } ``` ```csharp // HydroValidationExtensions.cs public static class HydroValidationExtensions { public static bool Validate(this TComponent component, IValidator validator) where TComponent : HydroComponent { component.IsModelTouched = true; var result = validator.Validate(component); foreach (var error in result.Errors) { component.ModelState.AddModelError(error.PropertyName, error.ErrorMessage); } return result.IsValid; } } ``` -------------------------------- ### Bind Input Elements Using `hydro-bind` Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Alternatively, use the `hydro-bind` attribute for property binding. This provides the same synchronization functionality as the `bind` attribute. ```razor ``` -------------------------------- ### Using `hydro-on` Tag Helper Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md The `hydro-on` tag helper can also be used to attach event handlers to elements, providing an alternative syntax for binding actions. ```razor ``` -------------------------------- ### Asynchronous Action Method Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/actions.md Hydro supports asynchronous actions. Simply declare the action method with an `async Task` return type and use `await` for asynchronous operations. ```csharp public async Task Add() { await database.Add(); } ``` -------------------------------- ### Pass Payload Object During Navigation Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/navigation.md To pass data between pages, use the `payload` parameter in the `Location` method. Define a record or class for your payload structure. ```csharp // Products.cshtml.cs public class Products : HydroComponent { public HashSet SelectedProductsIds { get; set; } // ... product page logic public void AddToCart() { Location(Url.Page("/Cart/Index"), new CartPayload(SelectedProductsIds)); } } ``` ```csharp // CartPayload.cs public record CartPayload(HashSet ProductsIds); ``` -------------------------------- ### Multiple File Upload Input Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Enable multiple file uploads by adding the `multiple` attribute to the file input. This allows users to select several files at once. ```razor @model AddAttachment
``` -------------------------------- ### Conditionally Skip Output with SkipOutput Method Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Use the `SkipOutput()` method within a Hydro action to conditionally prevent component re-rendering. Note that state changes will not be persisted when output is skipped. ```csharp public class ProductList : HydroComponent { public void Save() { if (this.Validate()) { SkipOutput(); Dispatch(new ProductSaved()); } } } ``` -------------------------------- ### Add Hydro Meta Tag to Layout Head Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/xsrf-token.md Ensure the `meta` tag for Hydro configuration is included in the `head` section of your layout file. This tag is necessary for the client-side integration of Hydro features, including the anti-forgery token. ```html ``` -------------------------------- ### Configure JSON Serializer Settings Source: https://github.com/hydrostack/hydro/blob/main/docs/content/advanced/additional-options.md Customize Hydro's JSON serialization by adding custom converters. This is useful for handling specific data types or formats. ```csharp builder.Services.AddHydro(options => { options.JsonSerializerSettings.Converters.Add(new MyCustomConverter()); }); ``` -------------------------------- ### Render an Alert View with Dynamic Attributes Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Render an alert message in Razor, incorporating the `Message` property and dynamically adding HTML classes. ```razor @model Alert
@Model.Message
``` -------------------------------- ### Enable Cookie Encryption Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/cookies.md Encode cookie values by setting the encryption parameter to true when using CookieStorage.Set or CookieStorage.Get. ```csharp CookieStorage.Set("theme", "light", encryption: true); ``` ```csharp CookieStorage.Get("theme", encryption: true); ``` -------------------------------- ### Read Payload Object After Navigation Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/navigation.md Access the payload passed from a previous page using the `GetPayload()` method within the `Mount` method or other component lifecycle methods. ```csharp // CartSummary.cshtml.cs public class CartSummary : HydroComponent { public CartPayload Payload { get; set; } public override void Mount() { Payload = GetPayload(); } // ... } ``` -------------------------------- ### Define DisplayField Hydro View with Child Content Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Define a C# class inheriting from HydroView to manage properties and child content for a view. Use Model.Slot() in the Razor view to render the passed child content. ```csharp // DisplayField.cshtml.cs public class DisplayField : HydroView { public string Title { get; set; }; } ``` ```razor @model DisplayField
@Model.Title
@Model.Slot()
``` ```razor 199 EUR ``` -------------------------------- ### Define Card Hydro View with Named Slots Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Create a C# class for a HydroView component like Card. Use Model.Slot("slotName") in the Razor view to render specific named child content passed by the caller. ```csharp // Card.cshtml.cs public class Card : HydroView; ``` ```razor @model Card
@Model.Slot("header")
@Model.Slot()
``` ```razor Laptop Information about the product Price: $199 ``` -------------------------------- ### Manage Local JS State with Alpine.js Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/js.md Utilize x-data to define local JavaScript state within a component and x-text to display it. Buttons can then update this state using x-on:click. ```razor @model Search
``` -------------------------------- ### Basic Form Validation with Data Annotations Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/form-validation.md Define validation rules using Data Annotations like [Required] and [MaxLength] in your Hydro component's model. Call the Validate() method before submitting to check for errors. ```csharp // ProductForm.cshtml.cs public class ProductForm : HydroComponent { [Required, MaxLength(50)] public string Name { get; set; } public async Task Submit() { if (!Validate()) { return; } // your submit logic } } ``` ```razor @model ProductForm
``` -------------------------------- ### Enable Background Navigation with hydro-link Attribute Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/navigation.md Use the `hydro-link` attribute on `` tags or parent elements to enable background loading of relative links, preventing full page reloads. ```html My page ``` ```html ``` -------------------------------- ### Invoke JavaScript Alert from Hydro View Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/js.md Execute a simple JavaScript alert from a button click in a Hydro view using the Client.ExecuteJs method. This is useful for quick debugging or user notifications. ```razor @model Search
``` -------------------------------- ### Display Cached Customer Data in Razor View Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md This Razor code shows how to bind an input element to a search phrase and iterate over the cached customer data to display it in an HTML table. The `await Model.Customers.Value` syntax is used to access the cached data. ```razor @model CustomerList @foreach (var customer in await Model.Customers.Value) { }
Customer name
@customer.Name
``` -------------------------------- ### Invoke JavaScript Console Log from C# Action Handler Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/js.md Log the current count to the browser console from a C# action handler using Client.ExecuteJs with a JavaScript template literal. This aids in debugging server-side state changes. ```csharp // Counter.cshtml.cs public class Counter : HydroComponent { public int Count { get; set; } public void Add() { Count++; Client.ExecuteJs($"console.log({Count})"); } } ``` -------------------------------- ### Define a Component Parameter Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Define a public property on a HydroComponent to serve as a parameter. This property can be set by a parent component. ```csharp public class Counter : HydroComponent { public int Count { get; set; } } ``` -------------------------------- ### Render Hydro Component using Custom Tag Source: https://github.com/hydrostack/hydro/blob/main/README.md Render a Hydro component in a Razor Page by using its custom tag name. ```razor ... ... ``` -------------------------------- ### Define a Transient Property with Attribute Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Mark a property with the `Transient` attribute to indicate that its value should not be persisted across requests. This is useful for temporary state like success messages. ```csharp public class ProductForm : HydroComponent { [Transient] public bool IsSuccess { get; set; } } ``` -------------------------------- ### Subscribe to an Event in a Parent Component Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Subscribe to an event in a parent component to react to events dispatched by child components. The component will re-render when the subscription is triggered. ```csharp public class Summary : HydroComponent { public Summary() { Subscribe(Handle); } public int CountSummary { get; set; } public void Handle(CountChangedEvent data) { CountSummary = data.Count; } } ``` -------------------------------- ### Render Hydro Components in Razor Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/components.md Use custom tag helpers, generic tag helpers, or extension methods to render Hydro components within your Razor Pages or other components. ```razor ``` ```razor ``` ```razor @await Html.Hydro("PageCounter") ``` ```razor @(await Html.Hydro()) ``` -------------------------------- ### Subscribe to an Event with a Subject Filter Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Subscribe to events and provide a subject filter to ensure the handler is only called for events matching the specified subject. The subject is often derived from component properties. ```csharp // TodoList.cshtml.cs public class TodoList : HydroComponent { public string ListId { get; set; } public List Todos { get; set; } public TodoList() { Subscribe(subject: () => ListId, Handle); } public void Handle(TodoRemoved data) { // will be called only when subject is ListId Todos.RemoveAll(todo => todo.TodoId == data.TodoId); } } ``` -------------------------------- ### Manual Binding Without `asp-for` Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Bind input elements manually by providing `name` and `value` attributes when not using the `asp-for` tag helper. The `bind` attribute still handles synchronization. ```razor ``` -------------------------------- ### Dispatch Event from Hydro Component Action Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Dispatch an event from a Hydro component's action method. This is suitable when dispatching is part of a larger action. ```csharp public class Counter : HydroComponent { public int Count { get; set; } public void Add() { Count++; Dispatch(new CountChangedEvent(Count)); } } ``` -------------------------------- ### Dispatch Event Directly from Client Code Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Dispatch an event directly from client-side code using `Model.Client.Dispatch`. This avoids an unnecessary server-side request and component rendering when the sole purpose is to dispatch an event. ```razor ``` -------------------------------- ### Dispatch an Event with a Subject Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Dispatch events with a subject to allow specific components to filter and handle them. The subject is typically an identifier relevant to the data or component. ```csharp // Todo.cshtml.cs public class Todo : HydroComponent { public string TodoId { get; set; } public string ListId { get; set; } public string Text { get; set; } public bool IsDone { get; set; } public void Remove(string id) { DispatchGlobal(new TodoRemoved { TodoId }, subject: ListId); } } ``` -------------------------------- ### Define a Transient Property without Setter Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Define a property with only a getter to make it transient. Its value is computed on the fly and not persisted. This is suitable for values that are always derived, like the current date. ```csharp public class ProductForm : HydroComponent { public DateTime CurrentDate => DateTime.Now; } ``` -------------------------------- ### Define a Custom Event Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Define a new event type using a C# record. This event will carry data related to a count change. ```csharp public record CountChangedEvent(int Count); ``` -------------------------------- ### Single File Upload Input Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Use a `type="file"` input with the `bind` attribute to enable single file uploads. The `asp-for` directive links the input to the component's property. ```razor @model AddAttachment
``` -------------------------------- ### Inlined Event Subscription in C# Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/events.md Subscribe to events directly within a component's constructor using a lambda expression. This is a concise way to handle event data. ```csharp // Summary.cshtml.cs public class Summary : HydroComponent { public Summary() { Subscribe(data => CountSummary = data.Count); } public int CountSummary { get; set; } } ``` -------------------------------- ### Set Component Parameter using Params Object Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/parameters.md Set component parameters by passing an anonymous object to the `params` attribute. This is useful for passing multiple parameters or complex objects. ```razor ``` -------------------------------- ### Global Error Handling Component Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/errors-handling.md This component subscribes to `UnhandledHydroError` events to display error messages to the user. It manages a list of toasts and provides a method to close them. ```csharp public class Toasts : HydroComponent { public List ToastsList { get; set; } = new(); public Toasts() { Subscribe(Handle); } private void Handle(UnhandledHydroError data) => ToastsList.Add(new Toast( Id: Guid.NewGuid().ToString("N"), Message: data.Message, Type: ToastType.Error )); public void Close(string id) => ToastsList.RemoveAll(t => t.Id == id); public record Toast(string Id, string Message, ToastType Type); } ``` -------------------------------- ### Define Hydro Component Properties Source: https://github.com/hydrostack/hydro/blob/main/docs/content/features/binding.md Define public properties in your Hydro component class to be bound to UI elements. These properties will hold the synchronized values. ```csharp public class NameForm : HydroComponent { public string FirstName { get; set; } public string LastName { get; set; } } ``` -------------------------------- ### Child View Calling Parent Action in Razor Source: https://github.com/hydrostack/hydro/blob/main/docs/content/utilities/hydro-views.md Render a button in `ChildView.cshtml` that calls the `LoadText` action of the parent component using `Reference()`. ```razor @model ChildView @{ var parent = Model.Reference(); } ```