I have decided to switch to tag helper as I have just realized how natural it looks and format in a sizeable cshtml file. I converted all essential elements to tag-helper equivalents. I need the following converted that I'll use for the remaining advanced controls:
A complex grid:
@(Html.Kendo().Grid(Model)
.Name("gridLetters")
.Columns(columns =>
{
columns.Bound(p => p.Identifier).Title("RL #").Filterable(false).Sortable(false).Width(160)
.HeaderHtmlAttributes(new { style = "k-text-center !k-justify-content-center" })
.HtmlAttributes(new { style = "k-text-center !k-justify-content-center" })
.ClientTemplate("<a href='" + Url.Action("View", "Letter", new { letterId = "#:Id#" }) + "'>#=Id#</i></a>");
columns.Bound(p => p.Subject);
columns.Bound(p => p.CompanyName).Title("Company");
columns.Bound(p => p.BrandName).Title("Brand");
columns.Bound(p => p.Location.Name).Title("Location");
columns.Bound(p => p.LetterTypeId).Title("RL Type").Width(150)
.HtmlAttributes(new { style = "text-align:center" })
.HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" })
.ClientTemplate("<span class='#=LetterType.BadgeInfo#' title='#=LetterType.Name#'>#=LetterType.Nickname#</span>");
columns.Bound(p => p.Status.Nickname).Title("Status").Width(150)
.HtmlAttributes(new { style = "text-align:center" })
.HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" })
.ClientTemplate("<span class='#=Status.BadgeInfo#' title='#=Status.Name#'>#=Status.Nickname#</span>");
columns.Bound(p => p.Id).Title("Act").Width(90).Filterable(false)
.HtmlAttributes(new { style = "text-align:center" })
.HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" })
.ClientTemplate(
"#if(StatusId == 1){#" +
" <a href='" + Url.Action("Create", "Letter", new { letterId = "#=Id#" }) + " ' title='Edit the RL'><i class='fa-duotone fa-pen-to-square'></i></a>" +
" <i class='fa-duotone fa-pipe'></i> " +
" <a href='" + Url.Action("ActionQuick", "Letter", new { letterId = "#=Id#" }) + " ' title='Start the RL Approval flow'><i class='fa-duotone fa-play'></i></a>" +
"#} else {#" + "" + "# } #"
);
})
.ToolBar(toolbar =>
{
toolbar.Excel();
toolbar.Search();
})
.Excel(excel => excel
.FileName($"DA CRL - My List Export - {DateTime.Now:yyyy-MM-dd}.xlsx")
.Filterable(true)
.ProxyURL(Url.Action("GridExcelExportSave", "Helper"))
)
.Scrollable(s => s.Height("auto"))
.Reorderable(r => r.Columns(false))
.Resizable(r => r.Columns(true))
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.Filterable()
.Sortable()
.ColumnMenu()
.Events(e => e.DataBound("onDataBound"))
.ClientDetailTemplateId("detailTemplate")
.DataSource(dataSource => dataSource
.Ajax()
.Sort(x => x.Add("Id").Descending())
.PageSize(20)
.ServerOperation(false)
)
)
@section Scripts {
<script id="detailTemplate" type="text/kendo-tmpl">
@(Html.Kendo().TabStrip()
.Name("tabStrip_#=Id#")
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items =>
{
items.Add().SpriteCssClasses("fa-duotone fa-clock-rotate-left").Text(" History").LoadContentFrom("GetLetterHistory", "Letter", new { masterGridId = "#=Id#" });
items.Add().SpriteCssClasses("fa-duotone fa-thumbs-up").Text(" Approvers").LoadContentFrom("GetLetterApprovers", "Letter");
items.Add().SpriteCssClasses("fa-duotone fa-magnifying-glass").Text(" Details").Content("");
items.Add().SpriteCssClasses("fa-duotone fa-link").Text("Attachments").Content("");
})
.ToClientTemplate()
)
</script>
<script>
var gridLetters = $("#gridLetters");
$(window).resize(function () {
resizeGrid();
});
function onDataBound(e) {
resizeGrid();
}
function resizeGrid() {
try {
if (gridLetters.options.scrollable !== true) {
gridLetters.setOptions({ scrollable: true });
}
} catch (e) {
}
$(".k-grid-content").css("height", $(window).height() - 310);
}
</script>
}
A form with Anti-Forgery Token, validation summary, DisplayFor, and Hidden field w/ jQuery changing values:
@Html.ValidationSummary()
@using (Html.BeginForm("Action", "Letter", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(m=>m.LetterId)
@Html.HiddenFor(m=>m.ActionId)
<div class="row">
<div class="btn-group d-flex">
<button id="btnActionApprove" type="button" class="btn btn-lg btn-success">
<i class="fa-duotone fa-thumbs-up fa-3x me-3 text-black"></i>
<span>
<span class="d-block"><b>Approve RL</b></span>
<span class="d-block fs-12px opacity-7">RL will proceed</span>
</span>
</button>
<button id="btnActionInfo" type="button" class="btn btn-lg btn-warning">
<i class="fa-duotone fa-messages-question fa-3x me-3 text-black"></i>
<span>
<span class="d-block"><b>More Info</b></span>
<span class="d-block fs-12px opacity-7">Info required</span>
</span>
</button>
<button id="btnActionReject" type="button" class="btn btn-lg btn-danger">
<i class="fa-duotone fa-thumbs-down fa-3x me-3 text-black"></i>
<span>
<span class="d-block"><b>Reject RL</b></span>
<span class="d-block fs-12px opacity-7">Cancel this RL</span>
</span>
</button>
</div>
</div>
<div class="row mt-5px">
<div class="col-12">
@(Html.Kendo().TextAreaFor(m => m.Comments)
.Size(ComponentSize.Large)
.Rounded(Rounded.Medium)
.FillMode(FillMode.Solid)
.Overflow(TextAreaOverflow.Auto)
.Resize(TextAreaResize.Vertical)
.Rows(6)
.Label(l => l.Content("Action Comments").Floating(true))
.HtmlAttributes(new { required = "required", validationmessage = "Please enter comments" })
)
</div>
</div>
<div class="row mt-5px">
<div class="col-2">
<button type="submit" class="btn btn-lg btn-success">Take Action</button>
</div>
</div>
}
@Html.DisplayFor(m=>m.Letter, "LetterView")
@section Scripts {
<script type="text/javascript">
$(function () {
$("#btnActionApprove").click(function () {
$("#ActionId").val("1");
});
$("#btnActionInfo").click(function () {
$("#ActionId").val("3");
});
$("#btnActionReject").click(function () {
$("#ActionId").val("2");
});
});
</script>
}
Cascading Combos:
<div class="row mt-3">
<div class="col-lg-4">
@(Html.Kendo().DropDownListFor(m => m.CategoryHeadId)
.Size(ComponentSize.Medium)
.Rounded(Rounded.Medium)
.FillMode(FillMode.Solid)
.OptionLabel("Select head category...")
.HtmlAttributes(new { style = "width: 100%" })
.DataTextField("Name")
.DataValueField("Id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetLookupCategoriesHead", "Api");
});
})
)
</div>
<div class="col-lg-4">
@(Html.Kendo().DropDownListFor(m => m.CategoryMainId)
.Size(ComponentSize.Medium)
.Rounded(Rounded.Medium)
.FillMode(FillMode.Solid)
.OptionLabel("Select main category...")
.HtmlAttributes(new { style = "width: 100%" })
.DataTextField("Name")
.DataValueField("Id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetLookupCategoriesMain", "Api")
.Data("filterMainCategories");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom(templatePrefixSolver + "CategoryHeadId")
)
</div>
<div class="col-lg-4">
@(Html.Kendo().DropDownListFor(m => m.CategorySubId)
.Size(ComponentSize.Medium)
.Rounded(Rounded.Medium)
.FillMode(FillMode.Solid)
.OptionLabel("Select sub-category...")
.HtmlAttributes(new { style = "width: 100%" })
.DataTextField("Name")
.DataValueField("Id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetLookupCategoriesSub", "Api")
.Data("filterSubCategories");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom(templatePrefixSolver + "CategoryMainId")
)
</div>
</div>
<script language="javascript" type="text/javascript" deffer>
function filterMainCategories() {
return {
headId: $("#@(templatePrefixSolver)CategoryHeadId").val()
};
}
function filterSubCategories() {
return {
headId: $("#@(templatePrefixSolver)CategoryHeadId").val(),
mainId: $("#@(templatePrefixSolver)CategoryMainId").val()
};
}
</script>
This will cover 100 of the web application as other controls are simpler than these three cases,