I see this answer from 7 years ago. Just wondering if there have been any changes or work arounds to get this to work.
Problem
We are trying to "extend" a Kendo DropDownList editor template by creating specific editor templates that set a minimum set of unique attributes, then passes that info to the base Kendo DropDownList editor template to help keep things DRY. (I mean, that is a core principle in development so to see the tools not allow it is a bit puzzling.)
But it seems the model type details are lost when calling the Base editor via Html.Partial
. And using a truly nested Html.EditorFor
within an editor template doesn't work either.
For example:
The model is marked as int?
, but if the model value is populated, the html markup is rendered as Required. If the model value is null, it is not.
Further, Validation Messages are genericized to the primitive type so instead of an error message like: "Account Id is required." you get "The Int32 field is required."
Model:
[Display(Name = "Expense Account")]
[UIHint("FinancialsChartOfAccounts-ExpenseEditor")]
public int? FinancialsPurchaseExpenseAccountId { get; set; }
"Derived" Editor
@{
var editorOptionsModel = new OTIS.Domain.DDLEditorOptionsModel();
editorOptionsModel.AreaName = "Shared";
editorOptionsModel.ControllerName = "ManageDDLs";
editorOptionsModel.ControllerAction = "GetChartOfAccountsExpense";
editorOptionsModel.Width = ViewData["WidthPixels"] != null ? (string)ViewData["WidthPixels"] : null;
editorOptionsModel.DefaultLabelText = ViewData["DefaultText"] != null ? (string)ViewData["DefaultText"] : "Select One...";
ViewData["ddlEditorOptionsModel"] = editorOptionsModel;
}
@Html.Partial("~/Views/_Base/Shared/EditorTemplates/DDLEditor.cshtml", (int?)Model)
"Base" Editor:
@using Kendo.Mvc.UI;
@using Kendo.Mvc.UI.Fluent;
@{
//set default option values
string strAreaName = "Shared";
string strControllerName = "ManageDDLs";
string strOptionLabel = "Select One...";
string strControllerAction = (string)ViewData["ControllerAction"];
string widthPixels = "100%";
//check to see if any options are passed in via view data from the view
if (ViewData["WidthPixels"] != null)
{
widthPixels = (string)(ViewData["WidthPixels"].ToString());
}
//see if a option model is passed in, and if so, use those values
var ddlEditorOptionsModel = new OTIS.Domain.DDLEditorOptionsModel();
if (ViewData["ddlEditorOptionsModel"] != null)
{
ddlEditorOptionsModel = (OTIS.Domain.DDLEditorOptionsModel)ViewData["ddlEditorOptionsModel"];
strAreaName = ddlEditorOptionsModel.AreaName ?? strAreaName;
strControllerName = ddlEditorOptionsModel.ControllerName ?? strControllerName;
strControllerAction = ddlEditorOptionsModel.ControllerAction ?? strControllerAction;
widthPixels = ddlEditorOptionsModel.Width ?? widthPixels;
strOptionLabel = ddlEditorOptionsModel.DefaultLabelText ?? strOptionLabel;
}
IDictionary<string, object> htmlAttributes = new RouteValueDictionary();
htmlAttributes["style"] = "width:" + widthPixels + ";min-width:250px;max-width:500px;";
if (ViewData["HtmlAttributes"] != null)
{
htmlAttributes = Html.MergeHtmlAttributes(ViewData["HtmlAttributes"], htmlAttributes);
}
DropDownListBuilder builder;
builder = Html.Kendo().DropDownListFor(model => model)
.HtmlAttributes(htmlAttributes)
.DataValueField("Value")
.DataTextField("DisplayText")
.OptionLabel(strOptionLabel)
.Template("#= data.DisplayText.replace(' ', ' ') #");
//set data source
if (ddlEditorOptionsModel.Data == null)
{
builder.DataSource(source =>
{
source.Read(read =>
{
read.Action(strControllerAction, strControllerName, new { area = strAreaName });
})
.ServerFiltering(true);
});
}
else
{
builder.BindTo(ddlEditorOptionsModel.Data);
}
if (ddlEditorOptionsModel.Height != null)
{
builder.Height(ddlEditorOptionsModel.Height.Value);
}
}
@(builder)
@Html.ValidationMessageFor(model => model)