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

Client Template DropDownBox Undefined

9 Answers 117 Views
This is a migrated thread and some comments may be shown as answers.
DD
Top achievements
Rank 1
DD asked on 10 May 2020, 09:31 AM

Hi,

 

I currently have a grid with InCell editing and batch updates enabled using MVC calls.

On this grid I have 2 columns which have drop down lists as a client template which displays data depending on what values are on the row.

 

Due to this, I am using AJAX binding for the drop down lists and value mappers.

 

Everything is working fine with one smallish bug when editing the cells.

I currently have an issue where if you sometimes double click or quickly click on the drop down list cells, the selection shows up as "undefined".

The control loads if you click it, and you can select items, but as soon as you click out, the text returns to "undefined".

 

When you try to save the changes, the property is passed through as null.

 

Because I need to have dynamic data on the drop down lists, I can't return hard coded values using the ViewBags as shown on the demoes.

 

What I've tried doing is to see if I can create an artificial delay on the grid events (BeforeEdit, Edit, CellClosed) but this has been no use as the cell loses focus as soon as you click somewhere else.

 

Is there some error that's occurring in the Kendo Javascript files which can be tweaked or to add some sort of delay to allow the drop down to load?

Or is there any way to prevent the "undefined" error from binding a null object until you cancel?

If the controls can just correctly bind after you get the "undefined" error would be good as well.

 

 

Thanks

9 Answers, 1 is accepted

Sort by
0
Tsvetomir
Telerik team
answered on 12 May 2020, 11:02 AM

Hi Daniel,

Thank you for the provided details of the scenario on hand. 

In general, when an editor is used within the ClientTemplate of a column, the Editable option should be set in order to disable the editing for the specific cell. Otherwise, the user will be switching between two different editors - one in the client template and one in the editor template.

columns.Bound(c=>c.FieldName).Editable("returnFalse");

// .  .  .

function returnFalse(e){
    return false;
}

Also, in order to have the DropDownList always visible, it should be initialized within the DataBound event handler. Could you share more details and the relevant code snippets of the current grid's setup? This way, I would have the chance to provide suggestions according your exact scenario. 

Looking forward to your reply.

 

Regards,
Tsvetomir
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
DD
Top achievements
Rank 1
answered on 13 May 2020, 10:17 PM

Thanks for the reply Tsvetomir,

 

Unfortunately this does not fix the issue as with the editable set and function returning false, clicking on the cell no longer allows it to be edited which is not what I want,

 

I have added the relevant sections below which I hope provides an explanation of what I'm trying to achieve:

 

01.@(Html.Kendo().Grid<ZooViewModel>()
02.    .Name("myzoogrid")
03.    .Columns(columns =>
04.    {
05.        columns.Bound(c => c.Staff)
06.            .HtmlAttributes(new
07.            {
08.                id = "userColumn"
09.            });
10.        columns.Bound(c => c.AnimalViewModel)   <== this is using a client template to a dropdown list and the values depend on what staff is selected.

 

11.            .HtmlAttributes(new
12.            {
13.                id = "animalViewModelColumn"
14.            })
15.            .Sortable(false).Groupable(false).Filterable(false)
16.            .ClientTemplate("#=AnimalViewModel.Name#");
17.        columns.Bound(c => c.SpeciesViewModel) <== this is also using a client template to a dropdown list, depends on values of AnimalViewModel
18.            .HtmlAttributes(new
19.            {
20.                id = "speciesViewModelColumn"
21.            })
22.            .Sortable(false).Groupable(false).Filterable(false)
23.            .ClientTemplate("#=SpeciesViewModel.Name#");
24.    })
25.    .ToolBar(toolbar =>
26.    {
27.        toolbar.Save();
28.    })
29.    .Editable(editable => editable.Mode(GridEditMode.InCell))
30.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31.    .DataSource(dataSource => dataSource
32.        .Ajax()
33.        .PageSize(100)
34.        .Read(read => read.Action("GetAnimalsList", "Animals")
35.            .Data("AnimalsListData"))
36.        .Update("UpdateAnimalsList", "Animals")
37.        .Batch(true)
38.        .Model(model =>
39.        {
40.            model.Id(p => p.ZooId);
41.            model.Field(p => p.StaffId).Editable(false);
42.            model.Field(p => p.AnimalViewModel).Editable(true);
43.            model.Field(p => p.SpeciesViewModel).Editable(true);
44.        })
45.        .Sort(sort =>
46.        {
47.            sort.Add(pr => pr.Staff).Ascending();
48.        })
49.    )
50.    .Mobile(MobileMode.Auto))

 

As you can see above, the client templates are added on the columns on line 10 and 17.

 

The client templates are in folder - Shared/EditorTemplates/AnimalsList.cshtml and an example for line 10 is as below:

01.@(Html.Kendo().DropDownList()
02.    // Name has to match the property being passed over from the grid.
03.    .Name("AnimalViewModel")
04.    .DataTextField("AnimalName")
05.    .DataValueField("AnimalId")
06.    .Filter("contains")
07.    .DataSource(source =>
08.    {
09.        source.Custom()
10.            .ServerFiltering(true)
11.            .ServerPaging(true)
12.            .PageSize(80)
13.            .Type("webapi")
14.            .Transport(transport =>
15.            {
16.                transport.Read(a => a.Url(animalsUrl)
17.                    .Data("animalsData"));
18.            })
19.            .Schema(schema =>
20.            {
21.                schema.Data("Data")
22.                    .Total("Total");
23.            });
24.    })
25.    .Events(e =>
26.    {
27.        e.Select("onAnimalSelect");
28.    })
29.    .Virtual(v => v.ItemHeight(26).ValueMapper("animalValueMapper"))
30.)

 

With the above setup, clicking on the cell causes the template's control to be refreshed (i.e. performs an ajax call), retrieves the data and displays the drop down on screen. (would be good to prevent the refresh from happening every time you click on the cell but that's for a different issue).

It works perfectly with no issues until you get to the point where if you click on the cell and leave too quickly (i think) the column is bound to "undefined" and stays that way even if you select a valid item afterwards.

When the column is set to "undefined", you then have to cancel changes or refresh the grid to be able to save a value to it again. If you try to save a value when it says "undefined", the property is set to NULL. Even if the initial selection shows up as "undefined", it would be fine if any subsequent clicks to a valid property binds it to a proper object but it doesn't seem to be doing that.

 

The easiest way to replicate the "leave too quickly" action is to double click on outside of the cell - without clicking on the drop down link, so the cell gets focus but the drop down list does not open.

 

I need to have an ajax drop down list in this cell as the values of this depends on the Staff ID value and so needs to be sent in a parameter.

 

Hope this clarifies things.

 

Thanks

0
Tsvetomir
Telerik team
answered on 15 May 2020, 01:29 PM

Hi Daniel,

Thank you for the provided code snippets. Indeed, the DropDownList widgets that you refer to are actually editor templates rather than client templates. What I have noticed that the DataTextField is set to "AnimalName" while the client template uses "Name" only. Can you ensure that the properties match correctly? 

01.@(Html.Kendo().DropDownList()
02.    // Name has to match the property being passed over from the grid.
03.    .Name("AnimalViewModel")
04.    .DataTextField("AnimalName") // Should match the property name in the AnimalViewModel (perhaps "Name")
05.    .DataValueField("AnimalId") // should match the Id property name

As per the request that is sent every time to the server-side, it is expected due to the fact that the DropDownList is initialized every time the cell enters edit mode. Therefore, with each initialization, it fetches the data from the server. 

Let me know if the issue is present.

 

Regards,
Tsvetomir
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
DD
Top achievements
Rank 1
answered on 15 May 2020, 01:59 PM

Hi Tsvetomir,

 

I have set the data text field name to match the grid's client template but I'm afraid the issue still persists.

Quickly entering and leaving the cell still causes it to be shown as undefined.

 

Is there any way to perhaps delay the binding by even 500ms  or something similar when you load the cell by any chance?

Or even a way to stop the "undefined" error to break the whole saving mechanism by returning null on the property?

The strange thing is that there are no javascript errors when it binds as "undefined" on the dev console which suggests there must be some internal try catch going on with this control so it doesn't show up as an error and just breaks.

 

The grid does everything that I need, apart from this one annoying issue.

 

Thanks

0
Tsvetomir
Telerik team
answered on 19 May 2020, 11:29 AM

Hi Daniel,

In general, we do our best to avoid introducing try-catch blocks in our source code and I can confirm that there are no more than a handful. The reasoning is to avoid having hidden exceptions that could cause a hard time for the developers for resolving any issues. 

As per the binding of the DropDownList, it should happen immediately regardless of the timing for closing the cell. 

In order for me to provide accurate suggestions, I would have to replicate the issue locally. Is it possible for you to share a sample project in which the defect could be observed?

Looking forward to your reply.

 

Regards,
Tsvetomir
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
DD
Top achievements
Rank 1
answered on 19 Jun 2020, 01:21 PM

Thanks for the reply Tsvetomir,

 

It's been difficult trying to create a sample solution trying to strip away any sensitive areas so I've not been able to create it for you.

 

However if you use the approach i've described exactly above, you can reproduce it quite easily.

 

It's just clicking on the cell outside of the drop down list and the whole cell will just display "undefined" and prevent the grid from being saved.

 

Searching the forums, this person has the exact same issue, and their work around was to use a ViewData passed in from initial load - something that I can not do because I need to call an AJAX function to retrieve the items depending on what row has been selected.

 

https://www.telerik.com/forums/dropdownlist-in-grid-cell-editor-template-shows-undefined

 

Would Konstantin (who answered on the previous post) be able to advise if it's possible to use the client template in the scenario i'm looking at?

0
Tsvetomir
Telerik team
answered on 23 Jun 2020, 12:13 PM

Hi Daniel,

Indeed, the fact that the DropDownList has a Name option set might be causing the issue. Is it possible for you to modify the editor template as follows:

@model AnimalViewModel

@(Html.Kendo().DropDownListFor(m=>m)

Be sure to remove the "Name" option at all. In general, the ASP.NET MVC is decorating the name attribute for the editors. When the name is set, there are occasions in which the name becomes the following "AnimalViewModel.AnimalViewModel" which is incorrect for the binding.

As per the thread that you have shared, the issue that is discussed there is most probably not related to the scenario we are currently working on.

Let me know if the issue persists.

 

Regards,
Tsvetomir
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
DD
Top achievements
Rank 1
answered on 28 Jun 2020, 09:38 PM

Thanks for the suggestion Tsvetomir,

 

Unfortunately, that still causes the same issue with "undefined" if you perform multi clicks as described previously.

 

 This is how the ViewModel is populated in the controller for the Grid and passed on:

...
.Select(a => new ZooViewModel{
    ...
    AnimalViewModel = new AnimalViewModel
    {
        AnimalId = a?.AnimalId,
        AnimalName = a?.AnimalName,
    },
    ...
})
...

 

And the AnimalViewModel is bound to the column in the grid like so:

columns.Bound(c => c.AnimalViewModel)
    .HtmlAttributes(new
    {
        id = "animalViewModelColumn"
    })
    .Sortable(false).Groupable(false).Filterable(false)
    .ClientTemplate("#=AnimalViewModel.AnimalName#")
    .Title("Animal")
    .Width("17em");

 

And the template looks like so (after your recommendation):

@(Html.Kendo().DropDownListFor(m => m)
    .DataTextField("AnimalName")
    .DataValueField("AnimalId")
    .Filter("contains")
    .DataSource(source =>
    {
        source.Custom()
            .ServerFiltering(true)
            .ServerPaging(true)
            .PageSize(80)
            .Type("webapi")
            .Transport(transport =>
            {
                transport.Read(a => a.Url(animalsUrl)
                    .Data("animalsData"));
            })
            .Schema(schema =>
            {
                schema.Data("Data")
                    .Total("Total");
            });
    })
    .Events(e =>
    {
        ...
    })
    .Virtual(v => v.ItemHeight(26).ValueMapper("..."))
    .Template(...)
)

 

 

Out of curiosity, I tried removing the client binding like so:

.ClientTemplate("#=AnimalViewModel#") - (removed the ".AnimalName")

 

And as expected, the grid shows the column as [Object object].

Performing the same actions as above to try and "break" the binding, I see it indeed breaks but this time shows up the foreign key ID of the column instead of saying 'undefined'.

This shows there is something wrong with the binding when you try to access the cell too quickly.

 

Interestingly, I've tried a separate approach, using the "Foreign Key" binding example which requires you to load all the Animals on page load into a ViewBag.

Binding the grid and client templates this way, the screen works perfectly as I cannot reproduce the error at all.

You can quickly click the cells or do anything to try and break the cell binding and it will always bind correctly - not getting the "undefined" error.

 

While this method would be good, it's not ideal because this means I have to return ALL records on the page load instead of a filtered list. e.g. Loading all animals in the zoo instead of animals available for the keeper which can be determined by looking at the row.

 

I'm still hoping there's a way this can be achieved without having to use the foreign key method due to the inconveniences I've explained above.

 

Would be great to hear any fixes for this.

 

Thanks

0
Tsvetomir
Telerik team
answered on 30 Jun 2020, 01:29 PM

Hi Daniel,

Based on the provided snippets, I have created a sample and I did not notice the "undefined" value is assigned to the column. Can you examine the attached example and let me know the steps that I need to follow in order to replicate the issue? 

Also, the foreignkey column can be bound to a remote data source without the need of having the data populated in a static collection:

https://demos.telerik.com/kendo-ui/grid/foreignkeycolumnbinding

Looking forward to your reply.

 

Kind regards,
Tsvetomir
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
DD
Top achievements
Rank 1
Answers by
Tsvetomir
Telerik team
DD
Top achievements
Rank 1
Share this question
or