A TabStrip as a ClientDetailTemplate

1 Answer 40 Views
Grid Template
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
DoomerDGR8 asked on 07 Dec 2023, 12:30 PM

Here is my grid setup:


@(Html.Kendo().Grid<AssetViewModel>()
      .Name("assetGrid")
      .Columns(columns =>
      {
	      columns.Bound(p => p.AssetId).Visible(false);
	      columns.Bound(p => p.AssetName).Title("Name").Filterable(false).Sortable(false)
	             .HtmlAttributes(new { style = "k-text-center !k-justify-content-center" }).HeaderHtmlAttributes(new { style = "k-text-center !k-justify-content-center" })
	             .ClientTemplate("<div class='identifier-container'><a href='" + Url.Action("ViewAsset", "Revenue", new { assetId = "#=AssetId#" }) + "'>#=AssetName#</a></div>");
		  columns.Bound(p => p.CategoryName).Title("Category").Width(130)
	             .HtmlAttributes(new { style = "text-align:center" }).HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" })
	             .ClientTemplate("<span class='#=CategoryCss#' title='#=CategoryName#'>#=CategoryName#</span>");
	      columns.Bound(p => p.ContactName)
	             .ClientTemplate("<span title='#+ContactName#'>#=ContactName#</span>");
	      columns.Bound(p => p.Age).Title("Age").Width(70)
	             .HtmlAttributes(new { style = "text-align:center" }).HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" });
	      columns.Bound(p => p.Cost).Title("Cost").Width(100)
	             .HtmlAttributes(new { style = "text-align:center" }).HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" });
	      columns.Bound(p => p.Investors).Title("Shares").Width(75)
	             .HtmlAttributes(new { style = "text-align:center" }).HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" });
	      columns.Bound(p => p.AssetId).Title("Act").Width(50).Filterable(false)
	             .HtmlAttributes(new { style = "text-align:center" }).HeaderHtmlAttributes(new { style = "text-align: center; justify-content: center" })
	             .ClientTemplate("<a href='" + Url.Action("EditAsset", "Revenue", new { assetId = "#=AssetId#" }) + " ' title='Edit the Asset'><i class='fa-duotone fa-pen-to-square fa-fw fa-lg theme-elevate-fa'></i></a>");
      })
      .ClientDetailTemplate(Html.Kendo().Template()
            .AddComponent(detailStrip => detailStrip
                  TabStrip().Name("tabStrip_${data.AssetId}")
                        .SelectedIndex(0)
                        .Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
                        .Items(tabs =>
                        {
                              tabs.Add().SpriteCssClasses("fa-duotone theme-elevate-fa fa-magnifying-glass ").Text("Details").LoadContentFrom("GetAssetDetails", "Revenue", new { masterGridId = "${data.AssetId}" });
                              tabs.Add().SpriteCssClasses("fa-duotone theme-elevate-fa fa-chart-mixed      ").Text("Charts ").LoadContentFrom("GetLetterApprovers", "Revenue", new { masterGridId = "${data.AssetId}" });
                              tabs.Add().SpriteCssClasses("fa-duotone theme-elevate-fa fa-clock-rotate-left").Text("History").LoadContentFrom("GetLetterDetails", "Revenue", new { masterGridId = "${data.AssetId}" });
                        })
            )
      )
      .Size(ComponentSize.Small)
      .ToolBar(toolbar => { toolbar.Search(); })
      .Search(s =>
      {
	      s.Field(o => o.AssetName,    "contains");
	      s.Field(o => o.CategoryName, "contains");
	      s.Field(o => o.ContactName,  "contains");
      })
      .Scrollable(s => s.Height("auto"))
      .Reorderable(r => r.Columns(false))
      .Resizable(r => r.Columns(true))
      .Pageable(p =>
      {
	      p.Refresh(false);
	      p.PageSizes(new[] { 5, 10, 20, 25, 50, 75, 100, 125, 150, 175, 200 });
	      p.ButtonCount(10);
	      p.Info(true);
      })
      //.Filterable()
      .Sortable()
      //.ColumnMenu(col => col.Filterable(false).Enabled(false))
      .DataSource(dataSource => dataSource
                .Ajax()
                .Read(read => read.Action("AssetListData", "Revenue"))
                .Sort(sort => sort.Add(nameof(AssetViewModel.AssetName)).Ascending())
                .PageSize(20)
	  ))

I'm having a few issues:

  1. Tab FontAwesome icons are not showing*
  2. the `masterGridId = "${data.AssetId}"` is not translating properly, and the actual parameter value sent back to action is a string: "${data.AssetId}"*
  3. At a given time, only one row must be expanded as the application is going to be used on a mobile screen
  4. Lastly, is there any chance of converting this into TagHelper format?

The '*' questions are most important.

1 Answer, 1 is accepted

Sort by
0
Alexander
Telerik team
answered on 12 Dec 2023, 08:53 AM

Hi Hassan,

Allow me to go over each of the inquiries in a more subject-oriented manner.

1) Tab FontAwesome icons are not showing:

Generally, the SpriteCSS class will try to decorate an existing class within boundaries. However, it would expect to gather the content that should be created through a CSS rule. My recommendation here would be to directly embed the required icon via the Text() API configuration whilst marking the Item as non-encoded.

For example:

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">

.ClientDetailTemplate(Html.Kendo().Template()
       .AddComponent(detailStrip => detailStrip.
             TabStrip().Name("tabStrip_${data.Id}")
                   .SelectedIndex(0)
                   .Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
                   .Items(tabs =>
                   {
                       tabs.Add().Text("Sofia <i class='fa fa-user m-2'></i>").Encoded(false);
                       tabs.Add().Text("England <i class='fa fa-plane m-2'></i>").Encoded(false);
                   })
      )
)

This should then produce the following result:

2) The `masterGridId = "${data.AssetId}"` is not translating properly, and the actual parameter value sent back to action is a string: "${data.AssetId}

Indeed, I completely agree with that the reported behavior is rather unorthodox, it appears that the behavior would be most notably be caused by the fact that the "${}" literal will be evaluated at a later stage once the component is fully rendered rather than runtime.

Meaning, that the compiler will treat the passed value as a string:

I have further explored any potential alternative and what I would recommend is to:

.Events(events => events.DetailExpand("onDetailExpand"))
  • Omit the "LoadContentFrom()" API configuration as illustrated in the aforementioned TabStrip snippet.
  • Within the DetailExpand handler, gather the parent Grid data Item by using the dataItem() method of the Grid. From there, gather the TabStrip associated with the expanded child Grid, and change its URL through the "_contentUrls" private field:
<script>
    function onDetailExpand(e) {

        setTimeout(function(){
            var tabStrip = $(e.detailRow).find(".k-tabstrip").data("kendoTabStrip");
            var parentItem = $("#grid").data("kendoGrid").dataItem(e.masterRow);
            console.log(parentItem);

            tabStrip._contentUrls = [
                `/Home/Load_Content?masterGridId=${parentItem.Id}`,
                `/Home/Load_Content2?masterGridId=${parentItem.Id}`,
            ];

            tabStrip.reload("li:first"); // Reload the content.

        }, 200) // Timeout is required in order for the TabStrip to be fully rendered.

    }
</script>

The aforementioned result should then produce the following result within the request's payload:

And should ensure that the query parameter is bound accordingly to the specified endpoint on the server-side:


3) At a given time, only one row must be expanded as the application is going to be used on a mobile screen:

I am not entirely certain of the exact scenario that needs to be achieved on your side, but what I would recommend is to expand a singular Detail Row by using the expandRow() method.

The following demo showcases this behavior being achieved in the DataBound handler of the Parent Grid:

Grid Hierarchy (Demo) - open the "View Source" tab to observe the Grid's configuration.

4) Lastly, is there any chance of converting this into TagHelper format?

I have answered a similar subject in a previous discussion of ours that can be found here:

Forum Thread

Attached you will find a runnable sample that showcases the approaches showcased in the first and second answers.

I hope this helps.

Kind Regards,
Alexander
Progress Telerik

Stay tuned by visiting our public roadmap and feedback portal pages. If you're new to the Telerik family, be sure to check out our getting started resources, as well as the only REPL playground for creating, saving, running, and sharing server-side code.
Tags
Grid Template
Asked by
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Alexander
Telerik team
Share this question
or