|
| 1 | +--- |
| 2 | +outline: deep |
| 3 | +--- |
| 4 | + |
| 5 | +# View tag helpers |
| 6 | + |
| 7 | +View tag helpers are an extension built in into Hydro that let you create new kind of view components (called view tag helpers) that can replace partials, editors and regular view components. |
| 8 | + |
| 9 | +Here is a basic example of a view tag helper called `Submit`: |
| 10 | + |
| 11 | +```c# |
| 12 | +// Submit.cshtml.cs |
| 13 | +
|
| 14 | +public class SubmitTagHelper : HydroTagHelper; |
| 15 | +``` |
| 16 | + |
| 17 | +```razor |
| 18 | +<!-- Submit.cshtml --> |
| 19 | +
|
| 20 | +@model SubmitTagHelper |
| 21 | +
|
| 22 | +<button class="btn btn-primary" type="submit"> |
| 23 | + Save |
| 24 | +</button> |
| 25 | +``` |
| 26 | + |
| 27 | +Now we can use our tag helper in any other razor view: |
| 28 | + |
| 29 | +```razor |
| 30 | +<!-- SomeForm.cshtml --> |
| 31 | +
|
| 32 | +<submit /> |
| 33 | +``` |
| 34 | + |
| 35 | +## Parameters |
| 36 | + |
| 37 | +View tag helpers use parameters to pass the data from a caller to the view. Example: |
| 38 | + |
| 39 | +```c# |
| 40 | +// Alert.cshtml.cs |
| 41 | +
|
| 42 | +public class AlertTagHelper : HydroTagHelper |
| 43 | +{ |
| 44 | + public string Message { get; set; } |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +```razor |
| 49 | +<!-- Alert.cshtml --> |
| 50 | +
|
| 51 | +@model AlertTagHelper |
| 52 | +
|
| 53 | +<div class="alert"> |
| 54 | + @Model.Message |
| 55 | +</div> |
| 56 | +``` |
| 57 | + |
| 58 | +Now we can set a value on the `message` attribute that will be passed to our `AlertTagHelper`: |
| 59 | + |
| 60 | +```razor |
| 61 | +<!-- Index.cshtml --> |
| 62 | +
|
| 63 | +<alert message="Success" /> |
| 64 | +``` |
| 65 | + |
| 66 | +Parameter names are converted to kebab-case when used as attributes on tags, so: |
| 67 | +- `Message` property becomes `message` attribute. |
| 68 | +- `StatusCode` property becomes `status-code` attribute. |
| 69 | + |
| 70 | +## Dynamic attributes |
| 71 | + |
| 72 | +All attributes passed to the view tag helper by the caller are available in a view definition, even when they are not defined as properties. |
| 73 | +We can use this feature to pass optional html attributes to the view, for example: |
| 74 | + |
| 75 | +```c# |
| 76 | +// Alert.cshtml.cs |
| 77 | +
|
| 78 | +public class AlertTagHelper : HydroTagHelper |
| 79 | +{ |
| 80 | + public string Message { get; set; } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +```razor |
| 85 | +<!-- Alert.cshtml --> |
| 86 | +
|
| 87 | +@model AlertTagHelper |
| 88 | +
|
| 89 | +<div class="alert @Model.Attribute("class")"> |
| 90 | + @Model.Message |
| 91 | +</div> |
| 92 | +``` |
| 93 | + |
| 94 | +Now we can set an optional attribute `class` that will be added to the final view: |
| 95 | + |
| 96 | +```razor |
| 97 | +<!-- Index.cshtml --> |
| 98 | +
|
| 99 | +<alert message="Success" class="alert-green" /> |
| 100 | +``` |
| 101 | + |
| 102 | +## Child content |
| 103 | + |
| 104 | +View tag helpers support passing the child html content, so it can be used later when rendering the tag. Example: |
| 105 | + |
| 106 | +```c# |
| 107 | +// DisplayField.cshtml.cs |
| 108 | +
|
| 109 | +public class DisplayFieldTagHelper : HydroTagHelper |
| 110 | +{ |
| 111 | + public string Title { get; set; }; |
| 112 | +} |
| 113 | +``` |
| 114 | + |
| 115 | +```razor |
| 116 | +<!-- DisplayField.cshtml --> |
| 117 | +
|
| 118 | +@model DisplayFieldTagHelper |
| 119 | +
|
| 120 | +<div class="display-field"> |
| 121 | + <div class="display-field-title"> |
| 122 | + @Model.Title |
| 123 | + </div> |
| 124 | +
|
| 125 | + <div class="display-field-content"> |
| 126 | + @Model.Slot() |
| 127 | + </div> |
| 128 | +</div> |
| 129 | +``` |
| 130 | + |
| 131 | +Usage: |
| 132 | + |
| 133 | +```razor |
| 134 | +<!-- SomePage.cshtml --> |
| 135 | +
|
| 136 | +<display-field title="Price"> |
| 137 | + <i>199</i> EUR |
| 138 | +</display-field> |
| 139 | +``` |
| 140 | + |
| 141 | +Remarks: |
| 142 | +- `Model.Slot()` renders the child content passed by the tag caller |
| 143 | + |
| 144 | + |
| 145 | +## Slots |
| 146 | + |
| 147 | +Slots are placeholders for html content inside view tag helpers that can be passed by the caller. Here is an example of a `Card` tag: |
| 148 | + |
| 149 | +```c# |
| 150 | +// Card.cshtml.cs |
| 151 | +
|
| 152 | +public class CardTagHelper : HydroTagHelper; |
| 153 | +``` |
| 154 | + |
| 155 | +```razor |
| 156 | +<!-- Card.cshtml --> |
| 157 | +
|
| 158 | +@model CardTagHelper |
| 159 | +
|
| 160 | +<div class="card"> |
| 161 | + <div class="card-header"> |
| 162 | + @Model.Slot("header") |
| 163 | + </div> |
| 164 | +
|
| 165 | + <div class="card-content"> |
| 166 | + @Model.Slot() |
| 167 | + </div> |
| 168 | +
|
| 169 | + <div class="card-footer"> |
| 170 | + @Model.Slot("footer") |
| 171 | + </div> |
| 172 | +</div> |
| 173 | +``` |
| 174 | + |
| 175 | +Usage: |
| 176 | + |
| 177 | +```razor |
| 178 | +<!-- SomePage.cshtml --> |
| 179 | +
|
| 180 | +<card> |
| 181 | + <slot name=“header”> |
| 182 | + <strong>Laptop</strong> |
| 183 | + </slot> |
| 184 | +
|
| 185 | + Information about the product |
| 186 | +
|
| 187 | + <slot name=“footer”> |
| 188 | + <i>Price: $199</i> |
| 189 | + </slot> |
| 190 | +</card> |
| 191 | +``` |
| 192 | + |
| 193 | +Remarks: |
| 194 | +- `Model.Slot("header")` renders the content of passed through `<slot name=“header”>` |
| 195 | +- `Model.Slot("footer")` renders the content of passed through `<slot name=“footer”>` |
| 196 | +- `Model.Slot()` renders the rest of the child content |
| 197 | + |
| 198 | +## Naming conventions |
| 199 | + |
| 200 | +View tag helpers follow the ASP.NET Mvc Tag Helpers naming conventions, which means when |
| 201 | +the view tag helper has suffix `TagHelper`, the prefix in kebab-case will be used as the tag name. Example: |
| 202 | + |
| 203 | +- `AlertTagHelper` gives `<alert />`. |
| 204 | +- `DisplayFieldTagHelper` gives `<display-field />`. |
| 205 | + |
| 206 | +It's possible to not use the default convention and specify the tag names by using attributes, for example: |
| 207 | + |
| 208 | +```c# |
| 209 | +// DisplayField.cshtml.cs |
| 210 | +
|
| 211 | +[HtmlTargetElement("DisplayField")] |
| 212 | +public class DisplayField : HydroTagHelper |
| 213 | +{ |
| 214 | + public string Title { get; set; }; |
| 215 | +} |
| 216 | +``` |
| 217 | + |
| 218 | +Usage: |
| 219 | + |
| 220 | +```razor |
| 221 | +<!-- SomePage.cshtml --> |
| 222 | +
|
| 223 | +<DisplayField title="Price"> |
| 224 | + 199 EUR |
| 225 | +</DisplayField> |
| 226 | +``` |
| 227 | + |
| 228 | +## Differences between Hydro components and view tag helpers |
| 229 | + |
| 230 | +**View tag helpers:** |
| 231 | +- Used to render views. |
| 232 | +- Not stateful or interactive. |
| 233 | +- Replacement for partial views, editors or regular view components. |
| 234 | +- Rerendered on each request. |
| 235 | + |
| 236 | +**Hydro components:** |
| 237 | +- Used to render functional components. |
| 238 | +- Stateful and interactive. |
| 239 | +- Should be used when state is needed. |
| 240 | +- Rerendered only in specific situations, like action calls or events. |
0 commit comments