Cascade DropDowns not working as a EditorTemplate

1 Answer 68 Views
DropDownList
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
DoomerDGR8 asked on 25 Jul 2022, 07:36 AM

Hi!

I have the following setup:

CsHtml:

	<div class="row mt-3">
		<div class="col-lg-4">
			@(Html.Kendo().DropDownListFor(m => m.CategoryHeadId)
			      .Size(ComponentSize.Medium)
				  .Rounded(Rounded.Medium)
				  .FillMode(FillMode.Solid)
				  .OptionLabel("Select head category...")
				  .HtmlAttributes(new { style = "width: 100%" })
				  .DataTextField("Name")
				  .DataValueField("Id")
				  .DataSource(source =>
				  {
					  source.Read(read =>
					  {
						  read.Action("GetLookupCategoriesHead", "Api");
					  });
				  })
				)
		</div>
		<div class="col-lg-4">
			@(Html.Kendo().DropDownListFor(m => m.CategoryMainId)
			      .Size(ComponentSize.Medium)
				.Rounded(Rounded.Medium)
				.FillMode(FillMode.Solid)
				.OptionLabel("Select main category...")
				.HtmlAttributes(new { style = "width: 100%" })
				.DataTextField("Name")
				.DataValueField("Id")
				.DataSource(source =>
				{
					source.Read(read =>
					{
						read.Action("GetLookupCategoriesMain", "Api")
						    .Data("filterMainCategories");
					})
					.ServerFiltering(true);
				})
				.Enable(false)
				.AutoBind(false)
				.CascadeFrom("CategoryHeadId")
				)
		</div>
		<div class="col-lg-4">
			@(Html.Kendo().DropDownListFor(m => m.CategorySubId)
				.Size(ComponentSize.Medium)
				.Rounded(Rounded.Medium)
				.FillMode(FillMode.Solid)
				.OptionLabel("Select sub-category...")
				.HtmlAttributes(new { style = "width: 100%" })
				.DataTextField("Name")
				.DataValueField("Id")
				.DataSource(source =>
				{
					source.Read(read =>
					{
						read.Action("GetLookupCategoriesSub", "Api")
						    .Data("filterSubCategories");
					})
					.ServerFiltering(true);
				})
				.Enable(false)
				.AutoBind(false)
				.CascadeFrom("CategoryMainId")
				)
		</div>
	</div>

Script:

@section Scripts {
	<script>
		function filterMainCategories() {
			return {
				headId: $("#CategoryHeadId").val()
			};
		}

		function filterSubCategories() {
			return {
				headId: $("#CategoryHeadId").val(),
				mainId: $("#CategoryMainId").val()
			};
		}
	</script>
}

Originally, this was a View on its own but later got refactored into an EditorTemplate. Since then, the second and third DropDowns are always disabled even if a parent makes a valid selection.

Console windows don't log any errors. I'm thinking it's an issue with the placement of the JS block. I tried placing it within a @Script section and directly. The thing that is really frustrating is that there are two views now using this EditorTemplate and one is working fine but the other has issues:

Create (Working):

	@using (Html.BeginForm("", "Letter", FormMethod.Post))
	{
		@Html.AntiForgeryToken()

		@Html.EditorFor(m => m, "Letter")

		<div class="row mt-3">
			<div class="col-md-1">
				<button type="submit" class="btn btn-primary w-100 me-5px" formaction="CreateSave" title="@(Model.IsUpdateCase ? "Update letter" : "Save letter")">@(Model.IsUpdateCase ? "Update" : "Save")</button>
			</div>
			<div class="col-md-1">
				<button type="submit" class="btn btn-default w-100" formaction="CreateSubmit" title="@(Model.IsUpdateCase ? "Update letter & submit" : "Save letter & submit")">Submit</button>
			</div>
		</div>
	}

ViewInfo (Not working):

	@using (Html.BeginForm("ViewInfo", "Letter", FormMethod.Post))
	{
		@Html.AntiForgeryToken()

		@Html.EditorFor(m => m.Letter, "Letter")

		<div class="row mt-3">
			<div class="col-md-1">
				<button type="submit" class="btn btn-primary w-100 me-5px" title="Submit">Submit</button>
			</div>
		</div>
	}

I have verified that the APIs are up and running and also the model for the template(s) is valid.

How do troubleshoot this behavior? And where should the script block files go per best practice? I think it should be in the template within the section.

1 Answer, 1 is accepted

Sort by
0
Accepted
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 25 Jul 2022, 07:31 PM

After inspecting the rendered UI element, I noticed that the second form had all Id prefixed due to EditorFor behavior:

@{
	var templatePrefixSolver = string.Empty;

	if (!string.IsNullOrWhiteSpace(ViewData.TemplateInfo.HtmlFieldPrefix))
	{
		templatePrefixSolver = $"{ViewData.TemplateInfo.HtmlFieldPrefix}_";
	}
}

<div class="row mt-3">
	<div class="col-lg-4">
		@(Html.Kendo().DropDownListFor(m => m.CategoryHeadId)
			.Size(ComponentSize.Medium)
			.Rounded(Rounded.Medium)
			.FillMode(FillMode.Solid)
			.OptionLabel("Select head category...")
			.HtmlAttributes(new { style = "width: 100%" })
			.DataTextField("Name")
			.DataValueField("Id")
			.DataSource(source =>
			{
				source.Read(read =>
				{
					read.Action("GetLookupCategoriesHead", "Api");
				});
			})
			)
	</div>
	<div class="col-lg-4">
		@(Html.Kendo().DropDownListFor(m => m.CategoryMainId)
			.Size(ComponentSize.Medium)
			.Rounded(Rounded.Medium)
			.FillMode(FillMode.Solid)
			.OptionLabel("Select main category...")
			.HtmlAttributes(new { style = "width: 100%" })
			.DataTextField("Name")
			.DataValueField("Id")
			.DataSource(source =>
			{
				source.Read(read =>
				{
					read.Action("GetLookupCategoriesMain", "Api")
				.Data("filterMainCategories");
				})
				.ServerFiltering(true);
			})
			.Enable(false)
			.AutoBind(false)
			.CascadeFrom(templatePrefixSolver + "CategoryHeadId")
			)
	</div>
	<div class="col-lg-4">
		@(Html.Kendo().DropDownListFor(m => m.CategorySubId)
			.Size(ComponentSize.Medium)
			.Rounded(Rounded.Medium)
			.FillMode(FillMode.Solid)
			.OptionLabel("Select sub-category...")
			.HtmlAttributes(new { style = "width: 100%" })
			.DataTextField("Name")
			.DataValueField("Id")
			.DataSource(source =>
			{
				source.Read(read =>
				{
					read.Action("GetLookupCategoriesSub", "Api")
					    .Data("filterSubCategories");
				})
				.ServerFiltering(true);
			})
			.Enable(false)
			.AutoBind(false)
			.CascadeFrom(templatePrefixSolver + "CategoryMainId")
		)
	</div>
</div>

<script>
	function filterMainCategories() {
		return {
			headId: $("#@(templatePrefixSolver)CategoryHeadId").val()
		};
	}

	function filterSubCategories() {
		return {
			headId: $("#@(templatePrefixSolver)CategoryHeadId").val(),
			mainId: $("#@(templatePrefixSolver)CategoryMainId").val()
		};
	}
</script>



Mihaela
Telerik team
commented on 28 Jul 2022, 07:21 AM

Hello Hassan,

I examined the shared code snippets, and I can confirm that the cascading configuration is correct.

Also, I prepared a demo project based on your setup, and it appears that the second DropDownList is activated as expected at my end when the first DropDownList is selected. The sample is attached for your reference.

The "id" of the input element of the DropDownListFor() is set to the name of the Model property. Attached you can find a screenshot.

Tags
DropDownList
Asked by
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
Share this question
or