Deferred Initialization
By default, the helpers output the initialization script of the component immediately after its HTML
markup. This scenario may not always be desired—for example, if the script files are registered at the bottom of the page, when you nest components, or when the Content Security Policy (CSP) is enabled.
The following example illustrates how the initialization script of a Button component is generated after its HTML
markup:
-
Button declaration
@(Html.Kendo().Button() .Name("primaryTextButton") .ThemeColor(ThemeColor.Primary) .Content("Primary Button") )
-
Generated HTML markup and initialization script
<button id="primaryTextButton" name="primaryTextButton" data-role="button" class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary" type="button" role="button" aria-disabled="false" tabindex="0"><span class="k-button-text">Primary Button</span></button> <script>kendo.syncReady(function(){jQuery("#primaryTextButton").kendoButton({"themeColor":"primary"});});</script>
To defer the initialization script of the Telerik UI for ASP.NET MVC components in the application, apply either of the following approaches:
Deferring Specific Components
To defer individual components:
-
Add the
Deferred()
method of the HTML helper . This option suppresses the immediate rendering of the<script>
tag after theHTML
of the component.@(Html.Kendo().NumericTextBox() .Name("age") .Deferred() )
Avoid deferring child components such as editors, components initialized inside client templates, or inside (inline or external Kendo UI templates). Otherwise, the initialization script of each child component will appear outside the parent component.
Serialize the component initialization script by using any of the following methods:
-
Call the
DeferredScripts
method. As a result, all previously deferred initialization statements will be output as an inline script.@Html.Kendo().DeferredScripts()
The
DeferredScripts
method accepts aBoolean
parameter which determines whether thescript
elements will be automatically rendered. This behavior is useful for rendering the deferred initialization scripts inside an existingscript
element.<script> @Html.Kendo().DeferredScripts(false) </script>
To render the deferred initialization script of a particular helper, use the
DeferredScriptsFor
method.@(Html.Kendo().NumericTextBox() .Name("age") .Deferred() ) <!-- other code --> @Html.Kendo().DeferredScriptsFor("age")
You can also use the
DeferredScriptsFor
method to suppress thescript
element that wraps the initialization script.<script> @Html.Kendo().DeferredScriptsFor("age", false) </script>
Deferring Components Globally
As of the R1 2023 SP1 release, you can configure a global option to defer the initialization scripts of all components in your application and avoid setting the deferred option for every component. This method simulates loading the initialization scripts as a JS
file through an HttpModule
.
To defer components globally:
-
Enable the
DeferToScriptFiles
setting in theGlobal.asax.cs
file.KendoMvc.Setup(x => { x.DeferToScriptFiles = true; });
-
Configure a
HttpModule
in theWeb.config
file that returns the cached scripts when the browser request them.<configuration> ... <system.webServer> <modules> <add name="KendoDeferredScriptsModule" type="Kendo.Mvc.KendoDeferredScriptsModule" /> </modules> </system.webServer> ... </configuration>
-
Serialize the script tag into a file by adding
@(Html.Kendo().DeferredScriptFile())
after all components declarations. Any components registered after it will not be included in the script.Alternatively, call the
DeferredScripts
method to format the components scripts as inline script.@(Html.Kendo().DeferredScriptFile())
@Html.Kendo().DeferredScripts()
The functionality of the StackLayout and the GridLayout components relies on inline styles. When the application is configured to defer the initialization of all components and return a
JS
file, as demonstrated above, the use of inline styles in those components will also be deferred. In this scenrio an additional stylesheet will be served by theHttpModule
.
Deferring Dynamically Loaded Components
When deferring the components globally and calling the DeferredScriptFile()
method, the simulated JS
file stores the initialization scripts of the components that are defined in the currently loaded View.
The following example shows the content of the generated JS
file when the loaded page contains only a TabStrip component with two tabs. The content of the second tab loads from a Partial View.
@{
ViewData["Title"] = "Home Page";
}
@(Html.Kendo().TabStrip()
.Name("tabstrip")
.Items(tabstrip =>
{
tabstrip.Add().Text("Engine").Selected(true)
.Content("Engine information");
tabstrip.Add().Text("Dimensions & Weights")
.LoadContentFrom(@Url.Action("Details", "Home"));
})
)
public class HomeController : Controller
{
public ActionResult Details()
{
return PartialView();
}
}
Partial View Content
kendo.syncReady(function() {
jQuery("#tabstrip").kendoTabStrip({
"contentUrls": ["", "/Home/Details"]
});
});
According to this example, if the Partial View that is returned by the Details
Action contains Telerik UI for ASP.NET MVC components, they will not be initialized because their initialization scripts are not included in the simulated kendo-deferred-scripts-XXX.js
file. To overcome this behavior, you need to call the DeferredScriptFile()
method in the Partial View after all components declarations. As a result, their initialization scripts will be stored in an external JS
file, which will load
with the Partial View.
The following example demonstrates how to load a Grid in a TabStrip item through a Partial View when the global deferred initialization is enabled.
@(Html.Kendo().TabStrip()
.Name("tabstrip")
.Items(tabstrip =>
{
tabstrip.Add().Text("Engine").Selected(true)
.Content("Engine information");
tabstrip.Add().Text("Dimensions & Weights")
.LoadContentFrom(@Url.Action("Details", "Home"));
})
)
public class HomeController : Controller
{
public ActionResult Details()
{
return PartialView();
}
}
@(Html.Kendo().Grid<OrderViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.OrderID);
columns.Bound(c => c.ShipName);
columns.Bound(c => c.OrderDate).Format("{0:MM/dd/yyyy}").Width(150);
})
.HtmlAttributes(new { style = "height:400px;" })
.Scrollable()
.Pageable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Read", "Grid"))
)
)
@(Html.Kendo().DeferredScriptFile())
When the Content Security Policy (CSP) is enabled, you need to use a nonce-source when loading components dynamically, for example, through Partial Views, or inside Windows or Dialogs.
The DeferredScriptFile()
method accepts a nonce, so you can call the method with the respective nonce value. Thereby, the CSP will allow the inline <script>
tag that loads the external script file, which contains the initialization scripts of the components from the Partial View.
As of the R2 2023 SP1, the
DeferredScriptFile()
method supports nonce.
@(Html.Kendo().DeferredScriptFile("Telerik-CSP-Example"))
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-Telerik-CSP-Example' https://kendo.cdn.telerik.com;" />
The following example showcases how to load a Grid in a TabStrip item through a Partial View when the CSP is enabled.
@(Html.Kendo().TabStrip()
.Name("tabstrip")
.Items(tabstrip =>
{
tabstrip.Add().Text("Engine").Selected(true)
.Content("Engine information");
tabstrip.Add().Text("Dimensions & Weights")
.LoadContentFrom(@Url.Action("Details", "Home"));
})
)
public class HomeController : Controller
{
public ActionResult Details()
{
return PartialView();
}
}
@(Html.Kendo().Grid<OrderViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.OrderID);
columns.Bound(c => c.ShipName);
columns.Bound(c => c.OrderDate).Format("{0:MM/dd/yyyy}").Width(150);
})
.HtmlAttributes(new { style = "height:400px;" })
.Scrollable()
.Pageable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Read", "Grid"))
)
)
@(Html.Kendo().DeferredScriptFile("Telerik-CSP-Example"))