Hydro views
Hydro views are an extension built in into Hydro that let you create new kind of view components that can replace partials, editors and regular view components.
Here is a basic example of a Hydro view called Submit
:
// Submit.cshtml.cs
public class Submit : HydroView;
// Submit.cshtml.cs
public class Submit : HydroView;
<!-- Submit.cshtml -->
@model Submit
<button class="btn btn-primary" type="submit">
Save
</button>
<!-- Submit.cshtml -->
@model Submit
<button class="btn btn-primary" type="submit">
Save
</button>
Now we can use our Hydro view in any other razor view:
<!-- SomeForm.cshtml -->
<submit />
<!-- SomeForm.cshtml -->
<submit />
Naming conventions
There are 2 ways of naming Hydro views:
Automatic naming with dash-case notation:
c#public class SubmitButton : HydroView;
public class SubmitButton : HydroView;
Usage:
<submit-button />
Manual naming with PascalCase using
nameof
:c#[HtmlTargetElement(nameof(SubmitButton))] public class SubmitButton : HydroView;
[HtmlTargetElement(nameof(SubmitButton))] public class SubmitButton : HydroView;
Usage:
<SubmitButton />
Parameters
Hydro views use parameters to pass the data from a caller to the view. Example:
// Alert.cshtml.cs
public class Alert : HydroView
{
public string Message { get; set; }
}
// Alert.cshtml.cs
public class Alert : HydroView
{
public string Message { get; set; }
}
<!-- Alert.cshtml -->
@model Alert
<div class="alert">
@Model.Message
</div>
<!-- Alert.cshtml -->
@model Alert
<div class="alert">
@Model.Message
</div>
Now we can set a value on the message
attribute that will be passed to our Alert
:
<!-- Index.cshtml -->
<alert message="Success" />
<!-- Index.cshtml -->
<alert message="Success" />
Parameter names are converted to kebab-case when used as attributes on tags, so:
Message
property becomesmessage
attribute.StatusCode
property becomesstatus-code
attribute.
Passing handlers as parameters
When you need to pass a handler to a Hydro view, you can use the Expression
type:
// FormButton.cshtml.cs
public class FormButton : HydroView
{
public Expression Click { get; set; }
}
// FormButton.cshtml.cs
public class FormButton : HydroView
{
public Expression Click { get; set; }
}
<!-- FormButton.cshtml -->
@model FormButton
<button on:click="@Model.Click">
@Model.Slot()
</button>
<!-- FormButton.cshtml -->
@model FormButton
<button on:click="@Model.Click">
@Model.Slot()
</button>
Usage:
<form-button click="@(() => Model.Save())">
Save
</form-button>
<form-button click="@(() => Model.Save())">
Save
</form-button>
Calling actions of a parent Hydro component
You can call an action of a parent Hydro component from a Hydro view using the Reference<T>
. Example:
Parent (Hydro component):
public class Parent : HydroComponent
{
public string Value { get; set; }
public void LoadText(string value)
{
Value = value;
}
}
public class Parent : HydroComponent
{
public string Value { get; set; }
public void LoadText(string value)
{
Value = value;
}
}
<!-- Parent.cshtml -->
@model Parent
<child-view />
<!-- Parent.cshtml -->
@model Parent
<child-view />
Child (Hydro view):
public class ChildView : HydroView;
public class ChildView : HydroView;
<!-- ChildView.cshtml -->
@model ChildView
@{
var parent = Model.Reference<Parent>();
}
<button on:click="@(() => parent.LoadText("Hello!"))">
Set text
</button>
<!-- ChildView.cshtml -->
@model ChildView
@{
var parent = Model.Reference<Parent>();
}
<button on:click="@(() => parent.LoadText("Hello!"))">
Set text
</button>
Dynamic attributes
All attributes passed to the Hydro view by the caller are available in a view definition, even when they are not defined as properties. We can use this feature to pass optional html attributes to the view, for example:
// Alert.cshtml.cs
public class Alert : HydroView
{
public string Message { get; set; }
}
// Alert.cshtml.cs
public class Alert : HydroView
{
public string Message { get; set; }
}
<!-- Alert.cshtml -->
@model Alert
<div class="alert @Model.Attribute("class")">
@Model.Message
</div>
<!-- Alert.cshtml -->
@model Alert
<div class="alert @Model.Attribute("class")">
@Model.Message
</div>
Now we can set an optional attribute class
that will be added to the final view:
<!-- Index.cshtml -->
<alert message="Success" class="alert-green" />
<!-- Index.cshtml -->
<alert message="Success" class="alert-green" />
Child content
Hydro views support passing the child html content, so it can be used later when rendering the view. Example:
// DisplayField.cshtml.cs
public class DisplayField : HydroView
{
public string Title { get; set; };
}
// DisplayField.cshtml.cs
public class DisplayField : HydroView
{
public string Title { get; set; };
}
<!-- DisplayField.cshtml -->
@model DisplayField
<div class="display-field">
<div class="display-field-title">
@Model.Title
</div>
<div class="display-field-content">
@Model.Slot()
</div>
</div>
<!-- DisplayField.cshtml -->
@model DisplayField
<div class="display-field">
<div class="display-field-title">
@Model.Title
</div>
<div class="display-field-content">
@Model.Slot()
</div>
</div>
Usage:
<!-- SomePage.cshtml -->
<display-field title="Price">
<i>199</i> EUR
</display-field>
<!-- SomePage.cshtml -->
<display-field title="Price">
<i>199</i> EUR
</display-field>
Remarks:
Model.Slot()
renders the child content passed by the tag caller
Slots
Slots are placeholders for html content inside Hydro views that can be passed by the caller. Here is an example of a Card
tag:
// Card.cshtml.cs
public class Card : HydroView;
// Card.cshtml.cs
public class Card : HydroView;
<!-- Card.cshtml -->
@model Card
<div class="card">
<div class="card-header">
@Model.Slot("header")
</div>
<div class="card-content">
@Model.Slot()
</div>
<div class="card-footer">
@Model.Slot("footer")
</div>
</div>
<!-- Card.cshtml -->
@model Card
<div class="card">
<div class="card-header">
@Model.Slot("header")
</div>
<div class="card-content">
@Model.Slot()
</div>
<div class="card-footer">
@Model.Slot("footer")
</div>
</div>
Usage:
<!-- SomePage.cshtml -->
<card>
<slot name=“header”>
<strong>Laptop</strong>
</slot>
Information about the product
<slot name=“footer”>
<i>Price: $199</i>
</slot>
</card>
<!-- SomePage.cshtml -->
<card>
<slot name=“header”>
<strong>Laptop</strong>
</slot>
Information about the product
<slot name=“footer”>
<i>Price: $199</i>
</slot>
</card>
Remarks:
Model.Slot("header")
renders the content of passed through<slot name=“header”>
Model.Slot("footer")
renders the content of passed through<slot name=“footer”>
Model.Slot()
renders the rest of the child content
Differences between Hydro components and Hydro views
Hydro views:
- Used to render views.
- Not stateful or interactive.
- Replacement for partial views, editors or regular view components.
- Rerendered on each request.
Hydro components:
- Used to render functional components.
- Stateful and interactive.
- Should be used when state is needed.
- Rerendered only in specific situations, like action calls or events.