0

I have a problem with the Telerik grid that I can't seem to find quite the exact problem anywhere. I'm following the demo from their site for Client Side Edit Templates. When going into edit mode it immediately dies saying select method is undefined from this js statement:

<script type="text/javascript">
    function onEdit(e) {
        $(e.form).find('#PageList').data('tDropDownList').select(function (dataItem) {
            return dataItem.Text == e.dataItem['PageName'];
        });
    }
</script>

Here is my view:

<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="Community_Portal_Admin" %>

<div class="gridFrame">

    <% Html.Telerik().Grid(Of IndustryPageContent)() _
            .Name("IndustryPageContent") _
            .DataKeys(Function(k) k.Add(Function(d) d.ID)) _
            .DataBinding(Function(db) db.Ajax() _
                        .Select("_GetPageContent", "Industry") _
                        .Update("_SetPageContent", "Industry")) _
            .Columns(Function(c) c.Bound(Function(d) d.IndustryID)) _
            .Columns(Function(c) c.Bound(Function(d) d.PageID)) _
            .Columns(Function(c) c.Bound(Function(d) d.PageActionID)) _
            .Columns(Function(c) c.Bound(Function(d) d.Content1)) _
            .Columns(Function(c) c.Bound(Function(d) d.Content2)) _
            .Columns(Function(c) c.Bound(Function(d) d.Content3)) _
            .Columns(Function(c) c.Bound(Function(d) d.Content4)) _
            .Columns(Function(c) c.Bound(Function(d) d.Content5)) _
            .Columns(Function(c) c.Command(Function(d) d.Edit().ButtonType(GridButtonType.Image)).Width(60)) _
            .Columns(Function(c) c.Bound(Function(d) d.ID).Hidden()) _
            .ClientEvents(Function(e) e.OnEdit("onEdit")) _
            .Editable(Function(c) c.Mode(GridEditMode.InForm).Enabled(True)) _
            .Scrollable(Function(s) s.Height("350px")) _
            .Pageable() _
            .Selectable() _
            .Render()
    %>

    <br />

    <%: Html.ActionLink("Close", "Index", "Configuration", Nothing, New With {.class = "t-button", .Style = "font-size:12px;"})%>

</div>

<script type="text/javascript">

    function onEdit(e) {

        $(e.form).find('#PageList').data('tDropDownList').select(function (dataItem) {
            return dataItem.Text == e.dataItem['PageName'];
        });
    }

</script>

Here is my controller action:

Function GetPageContent() As ActionResult

    Try
        ViewData("PageList") = SharedListDataRepository.PageList()

        Return PartialView()

    Catch ex As Exception
        Throw
    End Try

End Function

Here is my helper to load the list data:

Public Shared Function PageList() As IEnumerable(Of ApplicationPage)

    Dim l As IEnumerable(Of ApplicationPage)

    Try
        l = (From d In New AdminIndustrySetupDataContext(TripleDESSecurity.Decrypt(SharedData.PortalCnx)).AdminApplicationPages Order By d.ID Select New ApplicationPage With {
                .ID = d.ID,
                .PageName = d.PageName
        }).AsEnumerable

        Return l

    Catch ex As Exception
        Throw
    Finally
        If Not l Is Nothing Then
            l = Nothing
        End If
    End Try

End Function 

Here is my model: as you can see it is decorated with the UIHint that is supposed to bring the control into the view but because the error is a js error on an "undefined" element that tells me that the list control never makes it onto the page. Which Firebug concurs with, it's just not there in the HTML

Imports System.ComponentModel.DataAnnotations
Imports System.Runtime.Serialization

<KnownType(GetType(IndustryPageContent))> _
Public Class IndustryPageContent

    <ScaffoldColumn(False)> _
    Public Property ID As Integer = 0
    Public Property IndustryID As Integer = 0
    <UIHint("PageList"), Required()> _
    Public Property PageID As Integer = 0
    Public Property PageActionID As Integer = 0
    Public Property Content1 As String = String.Empty
    Public Property Content2 As String = String.Empty
    Public Property Content3 As String = String.Empty
    Public Property Content4 As String = String.Empty
    Public Property Content5 As String = String.Empty

    Public Sub New()
        MyBase.New()
    End Sub

End Class

And lastly here is my list control:

<%@ Control Language="vb" Inherits="System.Web.Mvc.ViewUserControl" %>

<% Html.Telerik().DropDownList() _
        .Name("PageList") _
        .BindTo(New SelectList(CType(ViewData("PageList"), IEnumerable), "ID", "PageName"))
%>

So my guess is that the javascript for select method fails because the UIHint isn't binding the control right so the control isn't there to call the select method on.

What am I missing? Are there any successful implementations of the Telerik grid with Ajax binding - with editing, using VB.NET and aspx, not razor? Or am I the only one painted into a corner with the restrictions I have to work with?

I've had nothing but problems using the Telerik demos, they're consistently incomplete and/or using a contradiction of methods that support eventually says "Oh you can't do that when doing this. Really? So why is it in the demo??

EDIT

This is final code for my grid that got it working:

 <% Html.Telerik().Grid(Of IndustryPageContent)() _
        .Name("IndustryPageContent") _
        .DataKeys(Function(k) k.Add(Function(d) d.ID)) _
        .DataBinding(Function(db) db.Ajax() _
                    .Select("_GetPageContent", "Industry") _
                    .Update("_SetPageContent", "Industry")) _
        .Columns(Function(c) c.Bound(Function(d) d.IndustryID)) _
        .Columns(Function(c) c.Bound(Function(d) d.PageID)) _
        .Columns(Function(c) c.Bound(Function(d) d.PageActionID)) _
        .Columns(Function(c) c.Bound(Function(d) d.Content1)) _
        .Columns(Function(c) c.Bound(Function(d) d.Content2)) _
        .Columns(Function(c) c.Bound(Function(d) d.Content3)) _
        .Columns(Function(c) c.Bound(Function(d) d.Content4)) _
        .Columns(Function(c) c.Bound(Function(d) d.Content5)) _
        .Columns(Function(c) c.Command(Function(d) d.Edit().ButtonType(GridButtonType.Image)).Width(60)) _
        .Columns(Function(c) c.Bound(Function(d) d.ID).Hidden()) _
        .Editable(Function(c) c.Mode(GridEditMode.InForm).Enabled(True)) _
        .Scrollable(Function(s) s.Height("350px")) _
        .Pageable() _
        .Selectable() _
        .Render()
%>

The ClientEvents line and the JS is not needed. The "Name" property of the dropdownlist must match the name of the property that it will be the list for. In this case, PageID and PageActionID. This is the code for 2 DDL that I have defined that work:

<%@ Control Language="vb" Inherits="System.Web.Mvc.ViewUserControl" %>

<% Html.Telerik().DropDownList() _
    .Name("PageID") _
    .BindTo(New SelectList(CType(ViewData("PageList"), IEnumerable), "ID", "PageIDandName")) _
    .Render()
%>

<%@ Control Language="vb" Inherits="System.Web.Mvc.ViewUserControl" %>

<% Html.Telerik().DropDownList() _
        .Name("PageActionID") _
        .BindTo(New SelectList(CType(ViewData("PageActionList"), IEnumerable), "PageActionID", "PageActionIDandAction")) _
        .Render()
%>
CD Smith
  • 6,597
  • 7
  • 40
  • 66

2 Answers2

0

I agree completely about their demos. They're not very well defined, but I can't complain too much; they at least have some documentation, and it is a free product.

You are correct: your select() is failing because the UIHint isn't getting your editor for whatever reason, so the line:

$(e.form).find('#ProductCategoryName').data('tDropDownList').select(function...

isn't finding your DDL. I've never gotten UIHint to work with client-side binding. That's not to say it can't work; maybe I'm just an idiot. But try using the ClientTemplate/EditorTemplate. It would be a bound column that looks something like:

.Columns(Function(c) c.Bound(Function(d) d.ProductCategory)).ClientTemplate("<#= ProductCategory ? ProdcutCategoryName : '' #>").EditorTemplateName("CategorySelector");

.select() is the wrong function to use here. try this:

onEdit(e){
    $ddl = $(e.cell).find('#ProductCategoryName');
    if($ddl.length > 0) {
        var ddl = $ddl.data('tDropDownList');
        ddl.fill(function(){
            if (e.dataItem['ProductCategory'] != null){
                    ddl.value(e.dataItem['ProductCategory'].Id)
            }
        });
     }
 }

This will make sure the ddl actually exists, and ensure that the ProductCategory is actually defined. ddl.fill() makes sure that the item is selected as the ddl is bound. ddl.value('') sets the value of the ddl, which selects the item you wanted. Depending on how flat your model is, you can actually clean that up a little more; I normally let my ViewModel objects go one deep. It adds a tiny bit of complexity at client-side, but I have no choice but to make as few trips to the server as is reasonable.

edit: if you really want to use UIHint for whatever reason, have you read through this page?

Will
  • 324
  • 2
  • 12
  • Thanks Will I'll give this a shot and let you know. Have you actually implemented this editing scenario successfully? – CD Smith Sep 04 '11 at 23:54
  • I would say the same thing, free is nice so can't complain right? Except we've actually spent the money on the big package. I get faster support here on SO tho. If I post a ticket to Telerik I don't get an answer till the next day. On SO I typically have an answer the same day. – CD Smith Sep 04 '11 at 23:57
  • No problem. Yup, I use this paradigm in several places in my app--what you see is pretty much a cut and paste with variable names changed. – Will Sep 05 '11 at 02:11
  • Aaahhh...yeah, we had the paid-for license at my last job. You have to account for bank holidays and whatnot with those guys, too. Here, you've got a bunch of people like me who don't have anything to do but answer stack overflow on the weekends. – Will Sep 05 '11 at 02:13
  • Ok so it turns out I don't even need the clientevents line in the grid and I don't need the onEdit javascript function at all. What truly matters is the UIHint line and the .Name() of the ddl. The Name must equal the exact name of the bound column name. With those 2 things in place, nevermind the js and the clientevents, it works just fine. See my above edited grid in view – CD Smith Sep 06 '11 at 18:22
  • Cool man, glad you got it working. I actually spent some more time working with it, and if your combo data's gonna be static on the page--which in most cases it will--it works pretty well. – Will Sep 07 '11 at 09:34
  • Thanks, now if I can only get this one working: http://stackoverflow.com/questions/7295372/model-properties-not-set-when-returning-to-the-controller-for-post This one is a complete mindjob... model not being posted back to controller, if I name both actions the same (overloaded) the wrong action tries to run, it's a total identity crisis! – CD Smith Sep 07 '11 at 16:56
  • Alright. I'll take a look at it. As if I don't get mind-f'd enough with MVC already...I'm always down for a challenge. :D – Will Sep 08 '11 at 06:37
0

Which is the right OnEdit method implementation? You have pasted two different code snippets:

function onEdit(e) {
  $(e.form).find('#ProductCategoryName').data('tDropDownList').select(function (dataItem) {
        return dataItem.Text == e.dataItem['ProductCategoryName'];
   });
}

and

function onEdit(e) {
   $(e.form).find('#PageList').data('tDropDownList').select(function (dataItem) {
        return dataItem.Text == e.dataItem['PageName'];
   });
}

The first will not work because the dropdownlist's name is "PageList" not "ProductCategoryName". jQuery returns empty result and .data("tDropDownList") returns null. That's why there is no "select" method.

On a side note we have released a new code library project which may help you implement the dropdown in grid scenario. You can check it here.

UPDATE: I think I saw what the problem is. Your DropDownList is never output because you are using a <% %> block instead of <%: %> or calling the Render(); method. Please change your code like this

<% Html.Telerik().DropDownList() _
        .Name("PageList") _
        .BindTo(New SelectList(CType(ViewData("PageList"), IEnumerable), "ID", "PageName")) _
        .Render()
%>

or this:

<%: Html.Telerik().DropDownList() _
        .Name("PageList") _
        .BindTo(New SelectList(CType(ViewData("PageList"), IEnumerable), "ID", "PageName"))
%>
Atanas Korchev
  • 30,562
  • 8
  • 59
  • 93
  • I had pasted the code here incorrectly, the code I'm actually using is in the edited question above. I checked out the project you suggested on Fri before leaving work but noticed it is a completely different implementation of how to achieve dropdownlist editing in a grid. Why doesn't the example posted in the demo work as it is supposed to? – CD Smith Sep 05 '11 at 23:18
  • Does our online example work when you browse it? The new project is a simplified version and we will make the online demo look the same. – Atanas Korchev Sep 06 '11 at 05:51
  • Atanas, the project you suggested to look at makes things even more difficult as it is using strongly typed dropdownlist which breaks my models. I can't change that, that's why I chose the client row edit demo and sample, which once I add the render method in I can see the drowdown but it fails to actually do any updating based on my selections. I'm going to zip up my project again and send it in via support ticket – CD Smith Sep 06 '11 at 14:26