Actions
Actions are methods defined in the component class. They allow you to react to user interactions.
Let's take a look at the following component:
// Counter.cshtml.cs
public class Counter : HydroComponent
{
public int Count { get; set; }
public void Add()
{
Count++;
}
}
// Counter.cshtml.cs
public class Counter : HydroComponent
{
public int Count { get; set; }
public void Add()
{
Count++;
}
}
A browser event of an element can be attached to an action method by using the on
tag helper:
<!-- Counter.cshtml -->
@model Counter
<div>
Count: <strong>@Model.Count</strong>
<button on:click="@(() => Model.Add())">
Add
</button>
</div>
<!-- Counter.cshtml -->
@model Counter
<div>
Count: <strong>@Model.Count</strong>
<button on:click="@(() => Model.Add())">
Add
</button>
</div>
<!-- Counter.cshtml -->
@model Counter
<div>
Count: <strong>@Model.Count</strong>
<button on:click="@(() => Model.Add())">
Add
</button>
</div>
<!-- Counter.cshtml -->
@model Counter
<div>
Count: <strong>@Model.Count</strong>
<button on:click="@(() => Model.Add())">
Add
</button>
</div>
Alternatively, you can use the hydro-on
tag helper:
<button on:click="@(() => Model.Add())">
Add
</button>
<button on:click="@(() => Model.Add())">
Add
</button>
The attribute on
can be defined as:
on:event="expression"
where:
- event: a definition of the event handler that is compatible with Alpine.js's x-on directive
- expression: C# lambda expression that calls the the callback method
Examples:
<button on:click="@(() => Model.Add(20))">
<div on:click.outside="@(() => Model.Close())">
<input type="text" on:keyup.shift.enter="@(() => Model.Save())" />
<button on:click="@(() => Model.Add(20))">
<div on:click.outside="@(() => Model.Close())">
<input type="text" on:keyup.shift.enter="@(() => Model.Save())" />
Parameters
If your action contains parameters, you can pass them in a regular way.
Example:
// Counter.cshtml.cs
public class Counter : HydroComponent
{
public int Count { get; set; }
public void Set(int newValue)
{
Count = newValue;
}
}
// Counter.cshtml.cs
public class Counter : HydroComponent
{
public int Count { get; set; }
public void Set(int newValue)
{
Count = newValue;
}
}
<!-- Counter.cshtml -->
@model Counter
<div>
Count: <strong>@Model.Count</strong>
<button on:click="@(() => Model.Set(20))">
Set to 20
</button>
</div>
<!-- Counter.cshtml -->
@model Counter
<div>
Count: <strong>@Model.Count</strong>
<button on:click="@(() => Model.Set(20))">
Set to 20
</button>
</div>
Results
Hydro provides multiple component results that can be returned from an action:
ComponentResults.Challenge
Calls
HttpContext.ChallangeAsync
and handles further redirectionsComponentResults.SignIn
Calls
HttpContext.SignInAsync
and handles further redirectionsComponentResults.SignOut
Calls
HttpContext.SignOutAsync
and handles further redirectionsComponentResults.File
Returns a file from the server
Examples:
// ShowInvoice.cshtml.cs
public class ShowInvoice : HydroComponent
{
public IComponentResult Download()
{
return ComponentResults.File("./storage/file.pdf", MediaTypeNames.Application.Pdf);
}
}
// ShowInvoice.cshtml.cs
public class ShowInvoice : HydroComponent
{
public IComponentResult Download()
{
return ComponentResults.File("./storage/file.pdf", MediaTypeNames.Application.Pdf);
}
}
// Profile.cshtml.cs
public class Profile : HydroComponent
{
public IComponentResult LoginWithGitHub()
{
var properties = new AuthenticationProperties
{
RedirectUri = RedirectUri,
IsPersistent = true
};
return ComponentResults.Challenge(properties, [GitHubAuthenticationDefaults.AuthenticationScheme]);
}
}
// Profile.cshtml.cs
public class Profile : HydroComponent
{
public IComponentResult LoginWithGitHub()
{
var properties = new AuthenticationProperties
{
RedirectUri = RedirectUri,
IsPersistent = true
};
return ComponentResults.Challenge(properties, [GitHubAuthenticationDefaults.AuthenticationScheme]);
}
}
JavaScript expression as a parameter
In some cases, like integrating with JavaScript libraries like maps, rich-text editors, etc. it might be useful to call a Hydro action with parameters evaluated on client side via JavaScript expression. You can use then Param.JS<T>(string value)
method, where:
T
: type of the parametervalue
: JavaScript expression to evaluate
If your parameter type is a string
, you can use a shorter version:
Param.JS(string value)
Example:
// Content.cshtml.cs
public class Content : HydroComponent
{
public void Update(string value)
{
// ...
}
}
// Content.cshtml.cs
public class Content : HydroComponent
{
public void Update(string value)
{
// ...
}
}
<!-- Content.cshtml -->
@model Content
<div>
<input type="text" id="myInput" />
<button on:click="@(() => Model.Update(Param.JS("window.myInput.value")))">
Update content
</button>
</div>
<!-- Content.cshtml -->
@model Content
<div>
<input type="text" id="myInput" />
<button on:click="@(() => Model.Update(Param.JS("window.myInput.value")))">
Update content
</button>
</div>
After clicking the button from the code above, Hydro will execute the expression window.myInput.value
on the client side, and pass it as a value
parameter to the Update
action.
NOTE: In case of using widely this feature in your component, you can add:
@using static Hydro.Param
and callJS
withoutParam.
prefix.
Asynchronous actions
If you want to use asynchronous operations in your actions, just change the signature of the method as in this example:
public async Task Add()
{
await database.Add();
}
public async Task Add()
{
await database.Add();
}