This is a migrated thread and some comments may be shown as answers.

Filtered foreign key drop down list based on another key

18 Answers 596 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Vince
Top achievements
Rank 1
Vince asked on 19 Apr 2017, 08:18 PM

Lets say I have two objects:

  • Person
  • Car

A person can own many cars. The grid contains a list of people and each person has a "primary car" attribute. This is obviously a foreign key to the car object. However, the drop down list should only contain cars that belong to that person. 

How do I accomplish this without doing something inefficient like:

public ActionResult Index()
{
        ViewData["cars"] = w.Cars.GetAll();
}

 

I understand I can use an/a EditorTemplate/ClientTemplate. However, every example I've found online has the inefficient step above. If I have a controller method such as:

public JsonResult GetCars([DataSourceRequest] DataSourceRequest request, int personId)
{
    return Json(w.GetCarsThatBelongToPerson(personId).ToDataSourceResult(request);
}

 

Can I not just use this controller method in the template as opposed to dumping the entire list of cars?

Thanks for reading!

 

18 Answers, 1 is accepted

Sort by
0
Viktor Tachev
Telerik team
answered on 21 Apr 2017, 11:52 AM
Hello Vince,

You can specify custom editor for the column as illustrated in the example below. When defining the Read() method for the DropDownList editor you can pass the persionId via the Data() method. This way, in the Read ActionMethod you can return only the cars related to specific person.



Regards,
Viktor Tachev
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Vince
Top achievements
Rank 1
answered on 21 Apr 2017, 12:09 PM

Hi Viktor,

 

I'm aware of that and have been using it. However, the example also has this:

model.Field(p => p.Category).DefaultValue(
                ViewData["defaultCategory"] as Kendo.Mvc.Examples.Models.CategoryViewModel);

 

If I don't send the entire list of cars, or in the above example categories, the drop down list appears blank for existing entries until the user expands the list.

0
Vince
Top achievements
Rank 1
answered on 21 Apr 2017, 12:10 PM

Oops, to clarify (is there an edit button I'm missing?)

The selected FK is stored correctly and appears correctly selected on existing entries. However, the selected "car" does not show up until the grid enters edit mode. The only way to solve this is to dump the entire list of cars as ViewData.

0
Viktor Tachev
Telerik team
answered on 25 Apr 2017, 08:04 AM
Hi Vince,

In order to pass only the relevant items to the DropDown component you should define the DataSource for it. You will bind it like illustrated in this example.

In order to pass additional data to the Read Action you should use the Data() method as described here.

The code for the DropDownList would look similar to the following:


@(Html.Kendo().DropDownListFor(m => m)
        .DataValueField("CategoryID")
        .DataTextField("CategoryName")
        .DataSource(d=>d
            .Read(read=>read.Action("GetCategories", "Controller").Data("additionalData"))
        )
)


The JavaScript function will look similar to the one below:

function additionalData(e) {
    var row = $("#grid").find(".k-edit-cell").parent();
    var grid = $("#grid").data("kendoGrid");
    var item = grid.dataItem(row);
 
    var id = item.ProductId;
 
    return {
        productId : id
    };
}


Note that you may need to adjust the code in order to match your configuration.


Regards,
Viktor Tachev
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Vince
Top achievements
Rank 1
answered on 22 Jan 2019, 05:48 PM

I need to bump this as this problem is still here nearly 2 years later.

Viktor, I already did everything you've mentioned in this thread prior to reading it. What I'm specifically asking for is skipping the ViewData step where we dump all said data.

c.ForeignKey(i => i.carId, (System.Collections.IEnumerable)ViewData["cars"], "Id", "ModelName").EditorTemplateName("CarDropDown")

 

Refer to the above code snippet. I explicitly want to remove (System.Collections.IEnumerable)ViewData["cars"] and force a fetch for cars when  a user selects a person. Either I'm blind, or the documentation is not clear because I have no idea how to do this.

 

Again, I do not want to dump ViewData from the controller on page load. I want to dynamically fetch said cars that belong to a person upon person selection. All the code is there already, but I am clueless as how to force the specific line above to deal with this.

0
Viktor Tachev
Telerik team
answered on 24 Jan 2019, 11:51 AM
Hello Vince,

The ForeignKey column needs all values for the respective field that will be bound to the dropdown editor. If you would like to read the items explicitly when the editor enters edit mode I suggest using a custom editor for the Grid. The example below illustrates how it can be configured:


In your scenario you should modify the configuration of the ComboBox/DropDown editor to use remote data like in this example:


Using this approach there will be no need to send the data for the dropdown editor in ViewData.


Regards,
Viktor Tachev
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Vince
Top achievements
Rank 1
answered on 25 Jan 2019, 04:14 PM

Viktor, the solution you provided is identical to your previous replies unless I am mistaken.

I find it hard to believe that Telerik would not have foreseen an issue like this, as this is quite common and would easily hit performance limitations in large scale applications, so I'm assuming I must be doing something wrong or hitting this from the wrong angle.

Example:

Assume there is a list of people. When a user selects a person, a grid is passed said person's ID and everything on the grid is filtered; this includes the cars the person owns. This is the point at which the grid should grab values, including the drop downs in said grid.

The problem is that the grid, with said custom drop down, requires every car in the database (as view data) to display correctly prior to entering edit mode. So the solution you've provided does not solve this problem.

0
Viktor Tachev
Telerik team
answered on 29 Jan 2019, 10:17 AM
Hello Vince,

If a custom editor is used it will not be necessary to pass all data for the DropDownList in ViewData. When the dropdown is configured to use remote binding it will call the Read ActionMethod when entering edit mode. Furthermore, you can limit the items that are returned from the server by sending additional arguments via the Data method.


Regards,
Viktor Tachev
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Vince
Top achievements
Rank 1
answered on 05 Feb 2019, 07:18 PM

Viktor, you specifically just said:

"When the dropdown is configured to use remote binding it will call the Read ActionMethod when entering edit mode."

Then how does it grab the values before entering edit mode? If the drop down only reads in edit, then the initial page loading will display blanks which goes back to the initial problem and the one I ran into initially.

0
Viktor Tachev
Telerik team
answered on 07 Feb 2019, 10:23 AM
Hello Vince,

I modified the custom editor example so that the dropdown editor was configured to read the data. The Read Action of the DropDownList was called when the relevant cell was edited. There was no call to the Read action before that on my end. Check out the video below showing the behavior I am observing.




Regards,
Viktor Tachev
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Jairo
Top achievements
Rank 1
Veteran
answered on 28 Feb 2020, 08:11 PM
I made this example as it is in the link but my problem is currently the kendo filter does not work for me, as I do for it to serve me
0
Alex Hajigeorgieva
Telerik team
answered on 03 Mar 2020, 01:36 PM

Hi, Jairo,

Can you provide more information about the issue that you are facing? This thread is about a Foreign Key column.

To implement DropDownList take a look at this online demo:

https://demos.telerik.com/aspnet-mvc/dropdownlist/serverfiltering

In case we have misunderstood the requirement, please feel free to get back to us with some more details.

Regards,
Alex Hajigeorgieva
Progress Telerik

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
0
Jairo
Top achievements
Rank 1
Veteran
answered on 14 May 2020, 08:22 PM

    columns.Bound(p => p.IdBodegaProyecto).Hidden();
    columns.Bound(p => p.ProyectoM).ClientTemplate("#=ProyectoM.DescripcionProyecto#").Width(380);
    columns.Bound(p => p.BodegaM).ClientTemplate("#=BodegaM.DescripcionBodega#").Sortable(true).Title("Bodega").Width(280).Filterable(false);
    if (ViewBag.IsPermisos.IsAuditar)

 

I have these two lists in my grid, I made the grid inline
  my problem is that the column filter doesn't work

my dropdownlis 

@model MaterialesBAL.Model.BodegaBodegaModel

@(Html.Kendo().DropDownListFor(m => m)
                  .AutoBind(false)
                  .ValuePrimitive(true)
                  .OptionLabel("Selecione una Bodega...")
                  .DataTextField("DescripcionBodega")
                  .DataValueField("IdBodega")
                  .DataSource(Source =>
                  {
                      Source.Read(read => read.Action("GetBodega", "BodegaProyectoes"))
                                .ServerFiltering(true);
                  })
)
@Html.ValidationMessageFor(m => m)

everything works fine except the column filters where I use the drop down list

Is there a way that the filters work?

0
Viktor Tachev
Telerik team
answered on 18 May 2020, 12:42 PM

Hi Jairo,

 

In order to implement filtering for a column that is bound to complex object it is recommended to use the approach described in the following article:

https://docs.telerik.com/kendo-ui/knowledge-base/grid-filter-column-with-dropdownlist

 

Regards,
Viktor Tachev
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Jairo
Top achievements
Rank 1
Veteran
answered on 18 May 2020, 11:09 PM

Hello Viktor Tachev,
Thanks for responding but still no data
I am using the event

.Events (e => e.Filter ("Filter"))
.Events (e => e.FilterMenuInit ("FilterMenu"))
and my function I have it like this
    function Filter (e) {
             dataSource: this.dataSource;
            if (e.field == "ProjectM" && e.filter! == null) {
                var currentFilter = []
                var filtersCount = e.filter.filters [0] .length
                var value = e.filter.filters [0] .value
                if (e.sender.dataSource.filter ()! == undefined) {
                  currentFilter = e.sender.dataSource.filter (). filters // Retain the other filters
                }
                currentFilter.push ({field: "ProyectoM.DescripcionProyecto", operatot: "eq", value: value})
                e.preventDefault ()
                e.sender.dataSource.filter (currentFilter)
              }
    }
    function FilterMenu (e) {
        dataSource: this.dataSource;
                if (e.field === "ProjectM") {
                $ (e.container) .find ('[type = "reset"]'). click (function (event) {
                  var filters = e.sender.dataSource.filter (). filters
                  for (let i = 0; i <= filters.length; i ++) {
                    if (filters [i] .field == "ProyectoM.DescripcionProyecto") {
                      filters.splice (i, 1);
                      e.sender.dataSource.filter (filters)
                    }
                  }
                })
              }
    }
 I have the column like this
   columns.Bound (p => p.ProyectoM) .ClientTemplate ("# = ProyectoM.DescripcionProyecto #"). Width (380);

//.Filterable(ftb => ftb.Mode(GridFilterMode.Menu))
    .Filterable(filterable => filterable
        .Extra(false)
        .Operators(operators => operators
            .ForString(str => str.Clear()
                .StartsWith("Starts with")
                .IsEqualTo("Is equal to")
                .IsNotEqualTo("Is not equal to")
            ))
        ) 

I don't know what I'm doing wrong but; (it doesn't work

0
Viktor Tachev
Telerik team
answered on 20 May 2020, 03:00 PM

Hello Jairo,

 

Thank you for the provided code. I examined it and it seems that the logic inside is checking for a property named ProjectM. However, the Grid column is bound to a field named ProyectoM.

Would you update the if statements in the Filter and FilterMenuInit handlers and let me know how the behavior changes?

 

Regards,
Viktor Tachev
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Jairo
Top achievements
Rank 1
Veteran
answered on 20 May 2020, 08:18 PM

good afternoon, thanks for replying
  According to what you tell me, ProyectoM comes from the main grid model so I can call my drop-down list

  public  class BodegaProyectoModel
    {
        public int IdProyecto { get; set; }
        public int IdBodegaProyecto { get; set; }
        [UIHint("EditarProyectoBodega")]
        [Required]
        public ProyectoBodegaModel ProyectoM { get; set; }

        [UIHint("EditarBodegaBodega")]
        [Required]
        public  BodegaBodegaModel BodegaM { get; set; }
    }

if conditions in filter events I place it to reference the column and my dropdown list

If I have to remove ProyectoM, what should go in the if and how do I refer to my column?

Thank you
stay tuned

0
Viktor Tachev
Telerik team
answered on 22 May 2020, 07:59 AM

Hi Jairo,

 

The updated if-statements would look similar to the highlighted rows below:

 

function Filter (e) {

	if (e.field == "ProyectoM" && e.filter! == null) {
		var currentFilter = []
		var filtersCount = e.filter.filters [0] .length
		var value = e.filter.filters [0] .value
		if (e.sender.dataSource.filter ()! == undefined) {
		  currentFilter = e.sender.dataSource.filter (). filters // Retain the other filters
		}
		currentFilter.push ({field: "ProyectoM.DescripcionProyecto", operatot: "eq", value: value})
		e.preventDefault ()
		e.sender.dataSource.filter (currentFilter)
	  }
}

function FilterMenu (e) { 
	if (e.field === "ProyectoM") {
		$ (e.container) .find ('[type = "reset"]'). click (function (event) {
		  var filters = e.sender.dataSource.filter (). filters
		  for (let i = 0; i <= filters.length; i ++) {
			if (filters [i] .field == "ProyectoM.DescripcionProyecto") {
			  filters.splice (i, 1);
			  e.sender.dataSource.filter (filters)
			}
		  }
		})
  }
}

 

Let me know how this modification works for you.

 

Regards,
Viktor Tachev
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Tags
Grid
Asked by
Vince
Top achievements
Rank 1
Answers by
Viktor Tachev
Telerik team
Vince
Top achievements
Rank 1
Jairo
Top achievements
Rank 1
Veteran
Alex Hajigeorgieva
Telerik team
Share this question
or