public static MvcHtmlString ImageButton(this HtmlHelper html, string imageUrl, string text, string onClickAction = null, bool showTextAfterImage = false, string additionalClasses = "", string defaultButtonClasses = "t-emsg-image-button k-button k-button-icon", string defaultImageClasses = "k-icon-image" ) { var builder = new FluentTagBuilder("a"); builder.AddCssClass(defaultButtonClasses); foreach (var addClass in (additionalClasses ?? string.Empty).Split(new [] { " " }, StringSplitOptions.RemoveEmptyEntries)) { builder.AddCssClass(addClass); } builder.AddAttribute("title", text); builder.AddAttribute("tabindex", "0"); if (!string.IsNullOrEmpty(onClickAction)) { builder.AddAttribute("onclick", onClickAction); } builder.AddToInnerHtml(new FluentTagBuilder("img") .AddAttribute("alt", text) .AddAttribute("src", imageUrl) .AddCssClass(defaultImageClasses) .ToString(TagRenderMode.SelfClosing)); if (showTextAfterImage) { builder.AddToInnerHtml(new FluentTagBuilder("span").AddCssClass("imageButtonText").AddToInnerHtml(text)); } return(new MvcHtmlString(builder.ToString())); }
public static MvcHtmlString UnobtrusiveImageButton(this HtmlHelper html, string imageUrl, string text, bool showTextAfterImage = false, string additionalClasses = "", Action <FluentTagBuilder> customizeButtonAnchor = null) { var anchorBuilder = new FluentTagBuilder("a"); anchorBuilder.AddCssClass("t-emsg-image-button k-button k-button-icon"); foreach (var addClass in (additionalClasses ?? string.Empty).Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)) { anchorBuilder.AddCssClass(addClass); } anchorBuilder.AddAttribute("title", text); anchorBuilder.AddAttribute("tabindex", "0"); anchorBuilder.AddToInnerHtml(new FluentTagBuilder("img") .AddAttribute("alt", text) .AddAttribute("src", imageUrl) .AddCssClass("k-icon-image") .ToString(TagRenderMode.SelfClosing)); if (showTextAfterImage) { anchorBuilder.AddToInnerHtml(new FluentTagBuilder("span").AddCssClass("imageButtonText").AddToInnerHtml(text)); } if (customizeButtonAnchor != null) { customizeButtonAnchor(anchorBuilder); } return(new MvcHtmlString(anchorBuilder.ToString())); }
/// <summary> /// Construct list for tree view. /// </summary> /// <typeparam name="TModel">Type of model.</typeparam> /// <typeparam name="TProperty">Type of selected property.</typeparam> /// <param name="helper">Html helper.</param> /// <param name="expression">Expression which selects property.</param> /// <param name="source">Soruce of tree view.</param> /// <returns>Tree view list as FluentTagBuilder.</returns> private static FluentTagBuilder ConstructList <TModel, TProperty>( this HtmlHelper <TModel> helper, Expression <Func <TModel, TProperty> > expression, TreeViewSource <TProperty> source) where TProperty : struct { // CSS classes string listCssClass = "tree-view-list"; string loadedCssClass = "tv-loaded"; // Construct tree view list FluentTagBuilder treeViewList = new FluentTagBuilder("ul") .AddCssClass(listCssClass); // If there is not any item return if (source == null || source.ItemList == null || source.ItemList.Count == 0) { return(treeViewList); } // If source is not empty add class treeViewList.AddCssClass(loadedCssClass); // Construct list items and add them to treeViewList foreach (TreeViewItem <TProperty> listItemSource in source.ItemList) { FluentTagBuilder listItem = helper .ConstructListItem(expression, listItemSource); treeViewList.AppendChild(listItem); } return(treeViewList); }
public static MvcHtmlString ActionLinkButton(this HtmlHelper helper, string text, [AspMvcAction] string action) { var builder = new FluentTagBuilder("a"); builder.AddCssClass("t-emsg-button k-button"); builder.AddToInnerHtml(new FluentTagBuilder("span").AddToInnerHtml(text)); builder.AddAttribute("href", helper.ToUrlHelper().Action(action)); return(new MvcHtmlString(builder.ToString())); }
public void BeginAccordionPanel(TextWriter writer, string title, string panelId, string parentAccordionId, bool expanded) { var li = new FluentTagBuilder("li", TagRenderMode.StartTag); if (expanded) { li.AddCssClass("k-state-active"); } writer.Write(li.ToString()); writer.Write(title); writer.Write(@"<div class=""k-content"">"); }
public static MvcHtmlString Button(this HtmlHelper helper, string text, string onClickFunction = null, string additionalCssClasses = null) { var builder = new FluentTagBuilder("a"); builder.AddCssClass("t-emsg-button k-button"); builder.AddAttribute("type", "button"); builder.AddAttribute("title", text); foreach (var addClass in (additionalCssClasses ?? string.Empty).Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)) { builder.AddCssClass(addClass); } builder.AddToInnerHtml(new FluentTagBuilder("span").AddToInnerHtml(text)); if (!string.IsNullOrEmpty(onClickFunction)) { builder.AddAttribute("onclick", onClickFunction); } return(new MvcHtmlString(builder.ToString())); }
public void BeginAccordionPanel(TextWriter writer, string title, string panelId, string parentAccordionId, bool expanded) { var li = new FluentTagBuilder("li", TagRenderMode.StartTag) .AddCssClass("accordion-item"); if (expanded) { li.AddCssClass("is-active"); } writer.Write(li.ToString()); writer.Write($@"<a href=""#"" class=""accordion-title"">{title}</a>"); writer.Write(@"<div class=""accordion-content"" data-tab-content>"); }
public override void Process(TagHelperContext context, TagHelperOutput output) { var urlHelper = UrlHelperFactory.GetUrlHelper( new ActionContext(ContextAccessor.HttpContext, new RouteData(), new Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor())); var itemsPerPage = (ItemsPerPage ?? 0); if (itemsPerPage == 0) { int.TryParse(ViewOptions.PerPageDefault, out itemsPerPage); } var currentPage = (CurrentPage ?? 1); var totalItems = (TotalItems ?? 0); if (totalItems > itemsPerPage) { var totalPages = (totalItems + (itemsPerPage - 1)) / itemsPerPage; string controller = String.IsNullOrEmpty(Controller) ? (ViewContext.ActionDescriptor as ControllerActionDescriptor)?.ControllerName : Controller; string action = String.IsNullOrEmpty(Action) ? "Index" : Action; var httpContext = ContextAccessor.HttpContext; var pageList = new List <string> { "«", "‹" }; switch (totalPages) { case 2: pageList.Add("1"); pageList.Add("2"); break; case 3: case 4: case 5: for (var i = 1; i < totalPages; i++) { pageList.Add(i.ToString()); } break; default: if (currentPage < 4) { for (var i = 1; i < 6; i++) { pageList.Add(i.ToString()); } } else { var endPage = currentPage + 2 < totalPages ? currentPage + 3 : totalPages + 1; for (var i = endPage - 5; i < endPage; i++) { pageList.Add(i.ToString()); } } break; } pageList.Add("›"); pageList.Add("»"); var list = new FluentTagBuilder("ul").AddCssClass("pagination pagination-sm") .MergeAttribute("style", "display:inline;"); dynamic routeValues = new ExpandoObject(); foreach (var page in pageList) { routeValues = new ExpandoObject(); if (page.IsNumeric()) { routeValues = new { page, itemsPerPage } } ; else if (page == "«") { routeValues = new { page = 1, itemsPerPage } } ; else if (page == "‹") { routeValues = new { page = currentPage - 1 > 0 ? currentPage - 1 : 1, itemsPerPage } } ; else if (page == "›") { routeValues = new { page = currentPage + 1 <= totalPages ? currentPage + 1 : totalPages, itemsPerPage } } ; else if (page == "»") { routeValues = new { page = totalPages, itemsPerPage } } ; foreach (var obj in httpContext.Request.Query) { if (!obj.Key.Equals("page", StringComparison.CurrentCultureIgnoreCase)) { routeValues[obj.Key] = obj.Value; } } var li = new FluentTagBuilder("li") .AppendHtml(Generator.GenerateActionLink(ViewContext, page, action, controller, string.Empty, string.Empty, string.Empty, routeValues, null)); if (page.IsNumeric()) { if (Convert.ToInt32(page) == currentPage) { li.AddCssClass("active"); } } list.AppendHtml(li); } routeValues = new ExpandoObject(); foreach (var obj in httpContext.Request.Query) { if (!obj.Key.Equals("page", StringComparison.CurrentCultureIgnoreCase)) { routeValues[obj.Key] = obj.Value; } } var perPageSelect = new FluentTagBuilder("select") .GenerateId("ddlResultsPerPage", "") .MergeAttribute("style", "width:auto;float:left;margin-right:15px;") .MergeAttribute("data-url", urlHelper.Action(Action, Controller, (object)routeValues)) .AddCssClass("itemCountDropdown form-control") .MergeAttribute("onchange", "javascript:window.location.href = $('.itemCountDropdown option:selected').attr('tag')"); routeValues.Page = 1; foreach (var item in ViewOptions.PerPageList) { routeValues.itemsPerPage = item.Value; item.Selected = item.Value == itemsPerPage.ToString(); var option = new FluentTagBuilder("option") .MergeAttribute("value", item.Value) .Append(item.Text) .MergeAttribute("tag", urlHelper.Action(action, controller, (object)routeValues)); if (item.Selected) { option.MergeAttribute("selected", "selected"); } perPageSelect.AppendHtml(option); } output.PostElement.AppendHtml(perPageSelect); output.PostElement.AppendHtml(list); } } }
/// <summary> /// Construct one row of list editor. /// </summary> /// <param name="model">Model object to construct list row according to.</param> /// <returns>Constructed row of list.</returns> private FluentTagBuilder ConstructListDataRow(TModel model) { // Declare and set css class names string listDataRowCss = "list-data-row"; string listDataFieldRowCss = "list-data-field-row"; string listDataCalptionFieldRowCss = "list-data-field-row__caption"; string listdataImageFiledRowCss = "list-data-field-row__iamge"; string listDataLabelCss = "list-data-display__label"; string listDataDisplayFieldCss = "list-data-display__field"; // Store current model for further use TModel oldModel = Helper.ViewData.Model; try { // Set model object of HtmlHelper to be able // to get correct display, editor and hidden for fields. Helper.ViewData.Model = model; // Create list data row and merge attributes FluentTagBuilder listDataRow = new FluentTagBuilder("div") .MergeAttributes(GetDataRowAttributes(model)) .AddCssClass(listDataRowCss); // Loop through each configured field and add them to the row. foreach (IFieldCore <TModel> fieldCore in FieldCollection) { /// Do not render field if provided condition is not met /// when list is managed at server side. if (BuilderType == ListEditorBuilderType.ManagedAtServerSide && !fieldCore.ShouldBeRendered(model)) { continue; } if (fieldCore.EditorType != EditorType.Hidden) { // If EditorType has not been set to Hidden, // construct normal field row // Initialize field FluentTagBuilder displayField = new FluentTagBuilder("div") .AddCssClass(listDataDisplayFieldCss); // If field should be rendered as image construct image tag // for the field otherwise costruct span for it. if (fieldCore.IsAsImage) { FluentTagBuilder iamgeField = new FluentTagBuilder("img") .MergeAttribute("src", fieldCore.Evaluate(model)); displayField.AppendChild(iamgeField); } else { FluentTagBuilder displaySpan = new FluentTagBuilder("span") .AppendChild(fieldCore.DisplayFor()); displayField.AppendChild(displaySpan); } // If this list editor will be managed at client side, // add hidden input field to be able to bind correctly. if (BuilderType == ListEditorBuilderType.ManagedAtClientSide) { displayField.AppendChild(fieldCore.HiddenFor()); } // Initialize row for label and field FluentTagBuilder fieldRow = new FluentTagBuilder("div") .AddCssClass(listDataFieldRowCss); // Add caption field row css class if needed if (fieldCore.IsAsCaption) { fieldRow.AddCssClass(listDataCalptionFieldRowCss); } // Add image filed row css class if needed if (fieldCore.IsAsImage) { fieldRow.AddCssClass(listdataImageFiledRowCss); } // Add label for field if needed. if (!fieldCore.IsWithoutLabel) { // Initialize label for field FluentTagBuilder label = new FluentTagBuilder("div") .AddCssClass(listDataLabelCss) .AppendChild(fieldCore.LabelFor()); fieldRow.AppendChild(label); } // Append display field to the row. fieldRow.AppendChild(displayField); // Add fieldRow to listEditorRow listDataRow.AppendChild(fieldRow); } else { // Initialize row for label and field FluentTagBuilder fieldRow = new FluentTagBuilder("div") .AddCssClass(listDataFieldRowCss) .AppendChild(fieldCore.HiddenFor()); // If EditorType has been set to Hidden, // just construct hidden input for field listDataRow.AppendChild(fieldRow); } } return(listDataRow); } finally { // Restore model of helper Helper.ViewData.Model = oldModel; } }
/// <summary> /// Generate page urls according to /// url generator and paging info. /// </summary> /// <param name="helper">HtmlHelper.</param> /// <param name="pagingInfo">Information about paging.</param> /// <param name="pageUrlGenerator">Url generator for pages.</param> /// <param name="htmlAttributes">Html attributes to add to links.</param> /// <returns>Generated html links.</returns> public static MvcHtmlString PageLinks( this HtmlHelper helper, PagingInfo pagingInfo, Func <int, string> pageUrlGenerator, object htmlAttributes) { if (pagingInfo == null) { throw new ArgumentNullException(nameof(pagingInfo)); } if (pageUrlGenerator == null) { throw new ArgumentNullException(nameof(pageUrlGenerator)); } string pagingContainerCss = "paging-container"; string pageLinkCss = "page-link"; string selectedLinkCss = "selected"; // Convert html attributes RouteValueDictionary attributes = HtmlHelper .AnonymousObjectToHtmlAttributes(htmlAttributes); // Initialize function to generate page link Func <int, FluentTagBuilder> constructPageLink = pageIndex => new FluentTagBuilder("a") .AddCssClass(pageLinkCss) .MergeAttribute("href", pageUrlGenerator(pageIndex)) .SetInnerText(pageIndex.ToString()); // Initialize function to constryct seperator dots Func <FluentTagBuilder> constructSeperatorDots = () => new FluentTagBuilder("span") .SetInnerText("..."); FluentTagBuilder pagingContainer = new FluentTagBuilder("div") .AddCssClass(pagingContainerCss); int lastPageIndex = pagingInfo.TotalPageCount; /// First of all define begining and ending index of page /// links which will be generated by loop. Maximum number of /// 9 pages can be generated by loop. First and last pages are added /// manually. // Maximum number of 4 pages should be rendered // before and after current page int rangeBeginIndex = Math.Max(2, pagingInfo.CurrentPage - 4); int rangeEndIndex = Math.Min(lastPageIndex - 1, pagingInfo.CurrentPage + 4); /// If there are more than 11 page links then 9 of them must be /// rendered by loop, otherwise all links must be displayed. // Get total count of page links which must be generated by loop. int totalCountOfPageLinksByLoop = Math.Min(lastPageIndex - 2, 9); /// Get current count of page links which will be generated by loop /// with current settings. For expample, if maximum page count is 100 /// and current page is 4, then two pages before current page (2, 3), /// current page itself and 4 pages after current page (5, 6, 7, 8) /// will be generated by loop. This means that total of 2 + 1 + 4 = 7 /// pages will be generated by loop, but this number must be 9. /// To accomplish this we have to add remaning pages from "before the current page" /// to the pages after current page. 4 must be generated before current page /// but this number is 2, then total of 6 pages should be generated after /// current page (5, 6, 7, 8, 9, 10). int currentPageCountByLoop = rangeEndIndex - rangeBeginIndex + 1; if (totalCountOfPageLinksByLoop > 5 && currentPageCountByLoop < totalCountOfPageLinksByLoop) { // Find remaing page count. // In the example above this is 4 - 2 = 2. int remainingPageCount = totalCountOfPageLinksByLoop - currentPageCountByLoop; // Add remaining pages to the before or after the current page. if (rangeBeginIndex == 2) { rangeEndIndex += remainingPageCount; } else if (rangeEndIndex == lastPageIndex - 1) { rangeBeginIndex -= remainingPageCount; } } // Add first page if (lastPageIndex >= 1) { FluentTagBuilder firstPage = constructPageLink(1) .MergeAttributes(attributes); if (1 == pagingInfo.CurrentPage) { firstPage.AddCssClass(selectedLinkCss); } pagingContainer.AppendChild(firstPage); // Add seperator dots there is gap between first page // and loop range begin index. if (rangeBeginIndex - 1 > 1) { pagingContainer.AppendChild(constructSeperatorDots()); } } // Add begaes in-between first and last for (int i = rangeBeginIndex; i <= rangeEndIndex; i++) { FluentTagBuilder pageLink = constructPageLink(i) .MergeAttributes(attributes); // Add selected class if needed if (i == pagingInfo.CurrentPage) { pageLink.AddCssClass(selectedLinkCss); } pagingContainer.AppendChild(pageLink); } // Add last page if needed if (lastPageIndex > 1) { // Add seperator dots if there is a gap between last page // and loop range end index. if (lastPageIndex - rangeEndIndex > 1) { pagingContainer.AppendChild(constructSeperatorDots()); } FluentTagBuilder lastPage = constructPageLink(lastPageIndex) .MergeAttributes(attributes); if (lastPageIndex == pagingInfo.CurrentPage) { lastPage.AddCssClass(selectedLinkCss); } pagingContainer.AppendChild(lastPage); } return(MvcHtmlString.Create(pagingContainer.Render())); }
/// <summary> /// Render list editor builder as list. /// </summary> /// <remarks> /// This is implementation of RenderList(object htmlAttributes) for /// both of IServerListEditorBuilder and IClientListEditorBuilder. /// </remarks> /// <param name="htmlAttributes">Html attributes to add to list.</param> /// <returns>ListEditorBuilder as MvcHtmlString format.</returns> public MvcHtmlString RenderList(object htmlAttributes) { // Collection name must be provided for proper binding // list editor which is manged at client side if (BuilderType == ListEditorBuilderType.ManagedAtClientSide && string.IsNullOrEmpty(CollectionName)) { throw new InvalidOperationException( "Name of collection must be provided before rendering."); } // Declare and set css class names string listEditorForCss = "list-editor-for"; string listDataCss = "list-data"; string listDataListActionContainerCss = "list-action_container"; // Get html attributes RouteValueDictionary attributes = HtmlHelper .AnonymousObjectToHtmlAttributes(htmlAttributes); // Create div element and merge attributes FluentTagBuilder listEditorFor = new FluentTagBuilder("div") .MergeAttributes(attributes) .AddCssClass(listEditorForCss); // If list editor will be managed at client side we will need an editor. if (BuilderType == ListEditorBuilderType.ManagedAtClientSide) { // Construct list editor. // List editor must be constructed prior to list data. // Otherwise validation attributes will be // added to hidden input elements inside list data. listEditorFor.AppendChild(ConstructListEditor()); } // Initialize list data div FluentTagBuilder listData = new FluentTagBuilder("div") .AddCssClass(listDataCss); // Initialize list action container and add to listData if needed. FluentTagBuilder listActionContainer = null; if (BuilderType == ListEditorBuilderType.ManagedAtClientSide) { listActionContainer = ConstructClientSideListActionContainer(); } else if (BuilderType == ListEditorBuilderType.ManagedAtServerSide) { listActionContainer = ConstructServerSideListActionContainer(); } if (listActionContainer != null) { listActionContainer.AddCssClass(listDataListActionContainerCss); listData.AppendChild(listActionContainer); } if (Data != null && Data.Count() > 0) { if (BuilderType == ListEditorBuilderType.ManagedAtClientSide) { // If builder will be managed at client side we need // to add indexers to be able to bind correctly // and action buttons for managing items. foreach (TModel model in Data) { using (Helper.BeginCollectionItem(CollectionName, false)) { // Append hidden indexer for correctly binding // data and action container for the row. FluentTagBuilder listDataRow = ConstructListDataRow(model) .AppendChild(Helper.HiddenIndexerForModel()) .AppendChild(ConstructClientSideListItemActionContainer(model)); // Add listDataRow to listData listData.AppendChild(listDataRow); } } } else { // If builder will be managed at server side we need // to add links for managing items. foreach (TModel model in Data) { FluentTagBuilder listDataRow = ConstructListDataRow(model) .AppendChild(ConstructServerSideListItemActionContainer(model)); // Add listDataRow to listData listData.AppendChild(listDataRow); } } } listEditorFor.AppendChild(listData); return(new MvcHtmlString(listEditorFor.Render())); }
private FluentTagBuilder GetPrevNext(int pageNumber, FluentTagBuilder span, bool activateLink, string title) { return(activateLink ? Tag.A(urlBuilder_(pageNumber)).Title(title).Html(span) : span.AddCssClass(GridClass.GridDisabled)); }
/// <summary> /// Render sorting controller. /// </summary> /// <param name="htmlAttributes">HtmlAttributes to add to control.</param> /// <returns>MvcHtmlString.</returns> public MvcHtmlString Render(object htmlAttributes) { if (SortingFieldCollection == null || SortingFieldCollection.Count == 0) { throw new InvalidOperationException("At list one field must be configured to enable sorting."); } string sortingControlCss = "sorting-control"; string controlFieldCss = "sorting-control-field"; string controlOrderCss = "sorting-control-order"; string controlHeaderCss = "sorting-control-header"; string controlListCss = "sorting-control-list"; string selectedCss = "selected"; // Initialize sorting field list FluentTagBuilder sortingFieldList = new FluentTagBuilder("ul") .AddCssClass(controlListCss); // Currently sorted according to this field ISortingFieldCore <TModel> currentlySortedField = null; // Loop thorugh configured fields and add links for them foreach (ISortingFieldCore <TModel> fieldCore in SortingFieldCollection) { string fieldPropertyName = fieldCore.GetPropertyName(); FluentTagBuilder link = new FluentTagBuilder("a") .MergeAttribute("href", SortFieldUrlGenerator(fieldPropertyName)) .SetInnerText(fieldCore.FieldLabel); FluentTagBuilder listItem = new FluentTagBuilder("li") .AppendChild(link); if (fieldPropertyName == Info.PropertyName) { // Store currently sorted field for further use // and add selected class to it. currentlySortedField = fieldCore; listItem.AddCssClass(selectedCss); } // Append item to list sortingFieldList.AppendChild(listItem); } // Initialize down icon FluentTagBuilder downIcon = new FluentTagBuilder("i") .AddCssClass("default-icons") .SetInnerHtml("keyboard_arrow_down"); // Initialize sorting field header FluentTagBuilder fieldHeaderSpan = new FluentTagBuilder("span") .SetInnerText(currentlySortedField.FieldLabel); FluentTagBuilder fieldHeader = new FluentTagBuilder("div") .AddCssClass(controlHeaderCss) .AppendChild(fieldHeaderSpan) .AppendChild(downIcon); // Initialize sorting field FluentTagBuilder sortingField = new FluentTagBuilder("div") .AddCssClass(controlFieldCss) .AppendChild(fieldHeader) .AppendChild(sortingFieldList); // Initialize order list FluentTagBuilder sortingOrderList = new FluentTagBuilder("ul") .AddCssClass(controlListCss); // Loop through availabel orders and create list items for them foreach (SortOrder order in Enum.GetValues(typeof(SortOrder))) { // Determine label string label = order == SortOrder.Asc ? AscendingLabel : DescendingLabel; FluentTagBuilder link = new FluentTagBuilder("a") .MergeAttribute("href", SortOrderUrlGenerator(order)) .SetInnerText(label); FluentTagBuilder listItem = new FluentTagBuilder("li") .AppendChild(link); if (order == Info.Order) { listItem.AddCssClass(selectedCss); } // Append item to list sortingOrderList.AppendChild(listItem); } // Initialize sorting order header string orderHeaderLabel = Info.Order == SortOrder.Asc ? AscendingLabel : DescendingLabel; FluentTagBuilder orderHeaderSpan = new FluentTagBuilder("span") .SetInnerText(orderHeaderLabel); FluentTagBuilder orderHeader = new FluentTagBuilder("div") .AddCssClass(controlHeaderCss) .AppendChild(orderHeaderSpan) .AppendChild(downIcon); // Initialize sorting order FluentTagBuilder sortingOrder = new FluentTagBuilder("div") .AddCssClass(controlOrderCss) .AppendChild(orderHeader) .AppendChild(sortingOrderList); // Extract htmlAttribytes RouteValueDictionary attributes = HtmlHelper .AnonymousObjectToHtmlAttributes(htmlAttributes); // Initialize sorting control, merge attributes and add controls FluentTagBuilder sortingControl = new FluentTagBuilder("div") .MergeAttributes(attributes) .AddCssClass(sortingControlCss) .AppendChild(sortingField) .AppendChild(sortingOrder); return(MvcHtmlString.Create(sortingControl.Render())); }
/// <summary> /// Create drop down button for selected property, /// with given source. /// </summary> /// <exception cref="ArgumentNullException"> /// When expression or source is null. /// </exception> /// <typeparam name="TModel">Type of model.</typeparam> /// <typeparam name="TProperty">Type of property.</typeparam> /// <param name="htmlHelper">HtmlHelper.</param> /// <param name="expression">Expression to select needed property.</param> /// <param name="source">Source of list to select from.</param> /// <param name="optionLabel">Label of drop down button if selection has not been made.</param> /// <param name="allowDefault">Allow to select default item without value.</param> /// <param name="htmlAttributes">Html attributes.</param> /// <returns>Drop down button mvc string.</returns> public static MvcHtmlString DropDownButtonFor <TModel, TProperty>( this HtmlHelper <TModel> htmlHelper, Expression <Func <TModel, TProperty> > expression, SelectList source, string optionLabel, bool allowDefault, object htmlAttributes) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (source == null || source.Items == null) { throw new ArgumentNullException(nameof(source)); } string dropDownCssClass = "dropdown-button"; string buttonContainerCssClass = "dropdown-button-container"; string headerCssClass = "dropdown-button-header"; string menuCssClass = "dropdown-menu"; string errorCssClass = "dropdown-button__error"; string selectedCssClass = "selected"; // Get model metadata ModelMetadata metadata = ModelMetadata .FromLambdaExpression(expression, htmlHelper.ViewData); // Convert html attributes RouteValueDictionary attributes = HtmlHelper .AnonymousObjectToHtmlAttributes(htmlAttributes); // Get modelValue string modelValue = string.Empty; if (metadata.Model != null && !string.IsNullOrEmpty(metadata.Model.ToString())) { modelValue = metadata.Model.ToString(); } // Define selected item string selectedValue = string.Empty; List <SelectListItem> listeItemSource = source .Items .Cast <SelectListItem>() .ToList(); // Check if selected value explicitly setted in the source selectedValue = listeItemSource .Where(m => m.Selected) .Select(m => m.Value) .FirstOrDefault(); /// If not explicitly set get model value as a selected value /// and set appropriate list item as selected if (string.IsNullOrEmpty(selectedValue) && !string.IsNullOrEmpty(modelValue)) { selectedValue = modelValue; SelectListItem listItem = listeItemSource .Where(m => m.Value.Equals(modelValue, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (listItem != null) { listItem.Selected = true; } } // Initialize parentDiv and merge attributes FluentTagBuilder dropDownDiv = new FluentTagBuilder("div") .MergeAttributes(attributes) .AddCssClass(dropDownCssClass); // Initialize and add css class of button container FluentTagBuilder buttonContainerDiv = new FluentTagBuilder("div") .AddCssClass(buttonContainerCssClass); // If any item has been selected // get text of that item as option label string buttonHeaderText = optionLabel; if (!string.IsNullOrEmpty(selectedValue)) { string selectedItemText = listeItemSource .Where(m => m.Value.Equals(selectedValue, StringComparison.OrdinalIgnoreCase)) .Select(m => m.Text) .FirstOrDefault(); // If selected item text found set buttonHeaderText to // this text if (!string.IsNullOrEmpty(selectedItemText)) { buttonHeaderText = selectedItemText; } } // Initialize down icon FluentTagBuilder downIcon = new FluentTagBuilder("i") .AddCssClass("default-icons") .SetInnerHtml("keyboard_arrow_down"); // Initialize button header FluentTagBuilder buttonHeader = new FluentTagBuilder("span") .AddCssClass(headerCssClass) .SetInnerText(buttonHeaderText); // Add icon and header into container buttonContainerDiv.AppendChild(downIcon).AppendChild(buttonHeader); // Append button container to content builder of dropdown dropDownDiv.AppendChild(buttonContainerDiv); // Initialzie drop down menu FluentTagBuilder menu = new FluentTagBuilder("ul") .AddCssClass(menuCssClass); // If allow default set to true add option to // select default item if (allowDefault) { FluentTagBuilder defaultItem = htmlHelper.CreateDropDownButtonMenuItem( expression, new SelectListItem { Text = optionLabel, Value = "", Selected = false }); // If model is null then add selected class to default item if (metadata.Model == null || string.IsNullOrEmpty(metadata.Model.ToString())) { defaultItem.AddCssClass(selectedCssClass); } menu.AppendChild(defaultItem); } // Loop throug list items and add them to menu foreach (SelectListItem listItem in listeItemSource) { // initialize menu item FluentTagBuilder menuItem = htmlHelper .CreateDropDownButtonMenuItem(expression, listItem); // If model equals to current list item // add selected class to menu item if (!string.IsNullOrEmpty(selectedValue) && string.Equals( listItem.Value, selectedValue, StringComparison.OrdinalIgnoreCase)) { menuItem.AddCssClass(selectedCssClass); } menu.AppendChild(menuItem); } // Append menu to dropdown dropDownDiv.AppendChild(menu); // Initialize error span and add css class MvcHtmlString validationMessage = htmlHelper.ValidationMessageFor(expression); FluentTagBuilder errorSpan = new FluentTagBuilder("span") .AddCssClass(errorCssClass) .AppendChild(validationMessage); // Append error span to dropdown dropDownDiv.AppendChild(errorSpan); return(new MvcHtmlString(dropDownDiv.Render())); }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { var urlHelper = _urlHelperFactory.GetUrlHelper( new ActionContext(_contextAccessor.HttpContext, new RouteData(), ViewContext.ActionDescriptor)); var actionDescriptor = (ViewContext.ActionDescriptor as ControllerActionDescriptor); if (String.IsNullOrEmpty(Action)) { Action = actionDescriptor.ActionName; } if (String.IsNullOrEmpty(Controller)) { Controller = actionDescriptor.ControllerName; } if (!String.IsNullOrEmpty(Area)) { RouteValues.Add("area", Area); } else { RouteValues.Add("area", ""); } dynamic routeValues = new ExpandoObject(); if (_routeValues != null && _routeValues.Count > 0) { foreach (var obj in _routeValues) { ((System.Collections.Generic.IDictionary <string, object>)routeValues)[obj.Key] = obj.Value; } } dynamic fbValues = new ExpandoObject(); if (_fbValues != null && _fbValues.Count > 0) { foreach (var obj in _fbValues) { ((System.Collections.Generic.IDictionary <string, object>)fbValues)[$"fb-{obj.Key}"] = obj.Value; } } var color = String.Empty; if (!String.IsNullOrEmpty(Icon)) { if (Icon.Contains(":")) { var iconValues = Icon.Split(':'); Icon = iconValues[0]; color = iconValues[1]; } } var cssClass = Icon ?? String.Empty; if (cssClass.StartsWith("fa-")) { cssClass = $"fa {cssClass}"; } var icon = new FluentTagBuilder("i") .AddCssClass(cssClass); if (!String.IsNullOrEmpty(color)) { icon.MergeAttribute("style", $"color:{color}"); } var content = await output.GetChildContentAsync(); var linkContent = content.GetContent(); if (String.IsNullOrEmpty(linkContent)) { linkContent = caption; } var link = _generator.GenerateActionLink(ViewContext, linkContent, Action, Controller, string.Empty, string.Empty, string.Empty, routeValues, null); var href = link.Attributes["href"]; var anchor = new FluentTagBuilder("a") .MergeAttribute("href", href) .MergeAttributes(fbValues) .AppendHtml(icon) .Append(" ") .Append(linkContent); if (IsFancybox) { anchor.AddCssClass("fancybox"); } if (IsDeleteLink) { anchor.AddCssClass("remove-object"); } var builder = new FluentTagBuilder("li") .AppendHtml(anchor); output.TagName = ""; output.Content.SetHtmlContent(builder); }