Skip to content

StuffOfInterest/LogicTagHelpers

Repository files navigation

Logic Tag Helpers

Tag helpers to provide control logic inside of cshtml pages.

CI Build Publish Build NuGet Package
.NET .NET NuGet

Introduction

Tag Helpers bring integration of server side code and HTML rendering. One thing missing is the ability to control logic flow (branching and looping) without falling back on embedded C# code inside of the HTML markup, via CSHTML. Logic Tag Helpers provides two selection ("if" and "switch") and four iteration ("while", "do", "for", and "foreach") tags that can allow creation of complex CSHTML pages with minimal embedded C# code.

Use of these tags is simple. First, import the NuGet package. Next, add one line to the _ViewImports.cshtml file. Finally, add the tags. The branch tags require no external C# code, although expressions can be used for setitng conditions. The looping tags will require at least one line to setup a variable, but most logic can be defined with lambda expressions instead of function references.

Tags

All six tags are derived from their C# language definitions.

Installation

Following line must be added to the _ViewImports.cshtml file for the logic tag helpers to be available.

@addTagHelper *, LogicTagHelpers

Tag Definitions

Below are simple examples for each of the logic tags.

if

Basic if/then/else may have at most one <then> and one <else> tag inside the <if> tag.

<if condition="Model.IsApproved">
   <then><p>The purchase was approved.</p></then>
   <else><p>The vendor declined your purchase.</p></else>
</if>

if-then

It is also possible to do an <if> tag with content directly nested inside. To avoid evaluating inner content to find <then> or <else> tags, a special <if-then> tag is available.

@{ var isCanceled = Model.IsOrdered && !Model.IsPaid; }
<if-then condition="isCanceled" direct="true">
   <p>Order was canceled due to non-payment on @Model.CancelDate.</p>
</if-then>

switch

There are two restrictions for the <switch> tag. First, the value attribute on the <case> tags must be of the same type as what the expression attribute on the <switch> tag evaluates to. Second, the value for each <case> tag may only appear once, which includes the catch all in the <default> tag.

<switch expression="Model.OrderStatusId">
   <case value="1"><p>Your order has been placed.</p></case>
   <case value="2"><p>Your order has been shipped.</p></case>
   <default><p>We don't know what happened to your order!</p></default>
</switch>

while

For a <while> loop, a control variable needs to be established outside of the loop and then a function, usually presented as a lambda expression, is evaluated before each pass through the loop.

@{ var x = 0; }
<while condition="() => x < 10">
   <p>This is line @x.</p>
   @{ x++; }
</while>

do

For a <do> loop, a control variable needs to be established outside of the loop and then a function, usually presented as a lambda expression, is evaluated after each pass through the loop.

@{ var x = 0; }
<do condition="() => x < 10">
   @{ x++; }
   <p>This is line @x.</p>
</do>

for

A <for> loop contains three attributes, an initialization, a condition test, and an update. Only the condition test is required as there is no way to exit the loop without one.

@{ int x = default; }
<for initialize="() => x = 0" condition="() => x < 10" update="() => x++">
   <span>content to display while condition is true</span>
</for>

foreach

The <foreach> requires a context object in order to hanlde iteration across a set of values. The context, a ForeachContext object, must be initialized before the loop and passed in as the iterator attribute. Inside of the loop, the Item property will be updated with the current item from the collection to operator on.

@{ var context = new ForeachContext<int>(Model.Numbers); }
<foreach iterator="context">
   <p>This is line @context.Item.</p>
</foreach>

Future

The only future features which may be added are a <continue> and a <break> tag for the loops to implement the same logic available in the C# language.

Contributing

If you wish to help with this project, you may submit an issue to let me know what needs fixed or added to the library. You may also submit a pull request if you want to make any improvements.

Author

This project was created by Delbert Matlock.