I have a switch control, placed inside of a tab control, in a client detail template, as part of a grid.
I need to bind the switch checked property, to a value stored in the grids dataset, which is a Boolean. However, the code causes the error:-
Preprocessor directives must appear as the first non-whitespace character on a line
The code is:-
<script id="subsubdetailsTemplate" type="text/kendo-tmpl">
@(Html.Kendo().TabStrip().Name("Tabstrip_#=ReportID#")
.Items(i =>
{
i.Add().Text("Report Details").Selected(true).Content(@<text>
<div>
<p> #=HideOnCatalogue#</p>
Hide from Catalogue?:
@(Html.Kendo().Switch()
.Name("switch_#=ReportID#")
.Events(e => e.Change("function(e){ switchChange(e, '#=ReportID#')}"))
.Checked(#=HideOnCatalogue#)
.Messages(c => c.Checked("YES").Unchecked("NO"))
.ToClientTemplate()
)
</div>
</text>);
}).ToClientTemplate())
</script>
How can I bind the value to the switch? I can display the value in a <p> tag without a problem, as well as passing the report ID to the function called when the switch is clicked.
Thanks
Hi Andrew,
Thank you for the code snippet and details provided.
Could you please share more details for this structure, as I am not totally sure which component is part of another and wherein the picture is the Switch component?
I guess that if we have a collection of values from the Model to the Switch - the 2nd instance of #=HideOnCalalog# is within the C# range, so the compiler is treating it as a #region preprocessor directive.
Once I have the whole picture, will try my best to achieve the desired behavior locally.
Looking forward to hearing back from you.
Kind Regards,
Anton Mironov
Sorry for the late replay, I've been on leave. The template is part of the grid, the code for which is:-
@(Html.Kendo().Grid<PBIReportCatalogue.Models.ViewReport> () .Name("catalogueGrid") .Columns(col => { col.Bound(o => o.ReportName).Title("Name"); col.Bound(o => o.WorkspaceName).Title("Workspace"); col.Bound(o => o.DatasetName).Title("Dataset"); col.Bound(o => o.WebURL).Title("Link").ClientTemplate("<a href='#=WebURL#' target='_blank' class='btn btn-info btn-sm' data-toggle=\"tooltip\" data-placement=\"top\" title=\"Click to open the report url.\" >View</a> "); col.Bound(o => o.ValidatedFlag).Title("Validated").ClientTemplate("#=ValidatedFlagGlyph#"); col.Bound(o => o.FunctionalFlag).Title("Functional?").ClientTemplate("#=FunctionalGlyph#").Filterable(filterable => filterable.UI("functionalFilter")); col.Bound(o => o.FinanceSystems).Title("Fin Sys?").ClientTemplate("#=FinanceSystemsGlyph#"); col.Bound(o => o.HasMetaData).Title("Has Tags?").ClientTemplate("#=HasTagsGlyph#"); col.Bound(o => o.HasTags).Title("Has Meta Data?").ClientTemplate("#=HasMetaDataGlyph#"); col.Bound(o => o.ReportID).Title("").ClientTemplate("#=EditButton#").Visible((bool)ViewBag.ShowEditbutton); }) .ClientDetailTemplateId("subsubdetailsTemplate") .Events(e=>e.DataBound("onDB")) .DataSource(ds => ds .Ajax() .Model(m => m.Id(p => p.ReportID)) .PageSize(25) .Read(rd => rd.Action("RD_Catlogue", "Catalogue").Data("antiForgery") ).Sort(s=> { s.Add("WorkspaceName").Ascending(); s.Add("ReportName").Ascending(); }) //.Group(group => group.Add("Folder", typeof(string), System.ComponentModel.ListSortDirection.Ascending)) ) .Pageable(p => p.Refresh(true)) .Sortable(s => s.SortMode(GridSortMode.MultipleColumn)) .Filterable() .ColumnMenu() .HtmlAttributes(new {style= "font-size:small" }) )
I've used templates in grids a lot successfully, but not with switches.
In similar scenarios the For() equivalent of the component is used: TextBoxFor, NumericTextBoxFor, etc.
The same is valid for the SwitchFor component as well:
https://github.com/telerik/kendo-ui-core/issues/4783
Hi Andrew,
Feel free to correct me if I misunderstood something. The requirement for the case is to use a Kendo UI Switch in a Kendo UI Grid using one of its boolean properties. If this is the case, I would recommend trying the following approach:
columns.Bound(p => p.Discontinued).ClientTemplate("<input class='customClass' #if (Discontinued) { # checked='checked' # } # type='checkbox' /> ");
// In the Grid: .Events(e => e.DataBound("onDataBound")) // The Event handler: function onDataBound() { this.tbody.find(".customClass").kendoSwitch() }
Attached is a sample project that I prepared for the case. It implements the approach above.
Make the needed tests locally with the project attached and let me know if further assistance is needed.
Looking forward to hearing back from you.
Best Regards,
Anton Mironov
Hi Andrew,
I am currently working on the case and will come back to you with an approach for achieving the desired behavior.
Thank you for your patience.
Kind Regards,
Anton Mironov
Hi Andrew,
Attached is a sample project that implements the requirements:
In order to achieve the desired behavior and bind every switch to a boolean property of the dataItem in the parent row of the Grid, I would recommend keeping the currently selected dataItem in a global scope variable. When a tab of the TabStrip is selected - get the input element and initialize the Switch with a value from the boolean property of the global scope saved dataItem.
Attached is a sample project that implements the approach above. Make the needed tests locally with the project attached and let me know if further assistance is needed.
In order to apply changes to the boolean property of the Model, handle the change event of the Switch and change the dataItem of the Grid.
Looking forward to hearing back from you.
Kind Regards,
Anton Mironov
I've tried this code, however it doesn't work for me, as I've defined the Switch using MVC, and have another event defined, as when the switch is changed, the flag is updated in the database. Also, I ahve the switch in the first tab of the tabstrip, so select isn't fired until the tabs are changed.
@(Html.Kendo().Switch() .Name("switch_#=ReportID#") .Events(e => e.Change("function(e){ switchChange(e, '#=ReportID#')}")) //.Checked(#=HideOnCatalogue#) .Size(ComponentSize.Small) .Messages(c => c.Checked("YES").Unchecked("NO")) .ToClientTemplate() )
This does seem to be a bug in the MVC wrappers not supporting binding properly.
Hi Andrew,
Thank you for the additional details provided.
The fact that the Switch is in the first tab is actually great news. In this case, the Switch could be initialized in the "DetailExpand" Event of the Grid. Here is an example of the event handler:
function onDetailExpand(e) { var dataItem = $("#grid").data("kendoGrid").dataItem(e.masterRow); var switchInstance = $("#switch_" + dataItem.OrderID).kendoSwitch().data("kendoSwitch"); switchInstance.check(dataItem.IsSwitchChecked); }
The values shown in the switch are the expected ones, so the value binding is correct. The saving of a change could be set via the Change Event handler as you mentioned. Let me know if further assistance with the update of the boolean property is needed.
Attached is the re-worked sample project that includes the approach with the Switch in the first tab.
Looking forward to hearing back from you.
Best Regards,
Anton Mironov
Anton, thanks for this, but I also have an event bound via the switch, using the MVC wrappers.
Can't this be done using a switch defined in Razor syntax?
Hi Andrew,
Thank you for the kind words.
The problem is that the Name of the Switch component is actually its Id.
As we are trying to initialize the Switch in a TabStrip where the current Model is not selected, the needed information for the name of the component is not available for the wrapper(MVC Switch), but this could be achieved with the Kendo component as in the sample project from my previous reply.
In order to implement the needed Event for the Switch(it is probably the "Change" Event as it is the one in the API for the component), I would recommend trying the following approach:
I hope this information helps.
Let me know if further information or assistance is needed.
Kind Regards,
Anton Mironov
Hi Andrew,
I am glad to hear that the desired behavior is now achieved.
If any further assistance or information is needed, do not hesitate to contact me and the team.
Best Regards,
Anton Mironov