"VM74214:2 Uncaught SyntaxError: Invalid or unexpected token .. " when adding a column with client template to a details grid

7 posts, 1 answers
  1. Kiril
    Kiril avatar
    4 posts
    Member since:
    Jun 2016

    Posted 19 Dec 2017 Link to this post

    Hi Progress team!

     

    I have a master grid and a details grid both using Ajax binding. I'm trying to add a button using ClientTemplate for both grids. It works fine for the master grid and fails for the details grid.

    Here is the code for the grids:

    001.@(Html.Kendo().Grid<dynamic>()
    002.            .Name("gridServiceResults")
    003.            .DataSource(dataSource =>
    004.            {
    005.                dataSource.Ajax().Events(e => e.RequestStart("gridRequestStart")).Model(m =>
    006.                {
    007.                    if (Model.PrimaryKey.Count() == 0)
    008.                    {
    009.                        throw new Exception("Service Configuration does not include an id column");
    010.                    }
    011.                    var id = Model.PrimaryKey[0].ColumnName;
    012.                    m.Id(id);
    013. 
    014.                    foreach (DataColumn column in Model.Columns)
    015.                    {
    016.                        var field = m.Field(column.ColumnName, column.DataType);
    017.                    }
    018.                })
    019.                .Sort(sort =>
    020.                {
    021.                    // SortFields = List<SortField>
    022.                    foreach (var sortField in ViewBag.SortFields)
    023.                    {
    024.                        var sortToAdd = sort.Add(Model.Columns[sortField.Name].ColumnName);
    025.                        if (sortField.SortDirection == DynamicPoint.Office365.CustomerVendorPortal.Common.Models.SortDirection.Descending)
    026.                        {
    027.                            sortToAdd.Descending();
    028.                        }
    029.                        else
    030.                        {
    031.                            sortToAdd.Ascending();
    032.                        }
    033.                    }
    034.                })
    035.                .PageSize((int)this.ViewData["PageSize"])
    036.                .Read(read => read.Action("Read", "Home", ViewBag.RouteValues).Data("getReadData()"));
    037.            })
    038.            .Columns(columnFactory =>
    039.            {
    040.                foreach (DataColumn column in Model.Columns)
    041.                {
    042.                    if (column.Caption != Constants.ResultDataTableSchema.HiddenCaption)
    043.                    {
    044.                        var c = columnFactory.Bound(column.DataType, column.ColumnName).HeaderHtmlAttributes(new { @class = "test-class" });
    045.                        c.Title(column.Caption);
    046.                        if (column.DataType == typeof(DateTime))
    047.                        { c.Format("{0:d}"); }
    048.                        if (column.DataType == typeof(Boolean))
    049.                        {
    050.                            c.HtmlAttributes(new { style = "text-align: center;" }).ClientTemplate("<input type='checkbox' disabled='disabled' " + "# if (" + column.ColumnName + ") { #" + "checked='checked'" + "# } #" + "/>");
    051.                            c.HeaderHtmlAttributes(new { style = "text-align: center;" });
    052.                        }
    053.                        if (column.DataType == typeof(Int32))
    054.                        {
    055.                            c.HtmlAttributes(new { style = "text-align: right;" });
    056.                            c.HeaderHtmlAttributes(new { style = "text-align: right" });
    057.                        }
    058.                        if ((column.DataType == typeof(Decimal)) || (column.DataType == typeof(float)) || (column.DataType == typeof(double)))
    059.                        {
    060.                            c.HtmlAttributes(new { style = "text-align: right;" }).Format("{0:n}");
    061.                            c.HeaderHtmlAttributes(new { style = "text-align: right" });
    062.                        }
    063.                    }
    064.                }
    065.                if (ViewBag.DetailsFormEnabled)
    066.                {
    067.                    columnFactory.Template(@<text></text>).ClientTemplate("#= serviceResultCommands(data) #");
    068.                }
    069.            })
    070.            .Scrollable(s => s.Height(770))
    071.            .ClientDetailTemplateId("gridResultChildItemsTemplate")
    072.            .Resizable(x => x.Columns(true))
    073.            .Filterable()
    074.            .Sortable()
    075.            .Pageable(x => x.PageSizes(new int[] { (int)this.ViewData["PageSize"], 10, 25, 50, 100 }).Numeric(true).Info(true).Input(true).Refresh(true))
    076.)
    077. 
    078.<script id="gridResultChildItemsTemplate" type="text/kendo-tmpl">
    079.    @(Html.Kendo().Grid<dynamic>()
    080.            .Name("gridServiceResultChildItems_#=" + Model.PrimaryKey[0].ColumnName + "#")
    081.            .DataSource(dataSource =>
    082.            {
    083.                dataSource.Ajax().Events(e => e.RequestStart("gridRequestStart")).Model(m =>
    084.                {
    085.                    if ((this.ViewBag.ChildItemViewModel.PrimaryKey != null) && (this.ViewBag.ChildItemViewModel.PrimaryKey.Length > 0))
    086.                    {
    087.                        var id = this.ViewBag.ChildItemViewModel.PrimaryKey[0].ColumnName;
    088.                        m.Id(id);
    089.                    }
    090. 
    091.                    foreach (DataColumn column in this.ViewBag.ChildItemViewModel.Columns)
    092.                    {
    093.                        var field = m.Field(column.ColumnName, column.DataType);
    094.                    }
    095.                })
    096.                .Sort(sort =>
    097.                {
    098.                    // SortFields = List<SortField>
    099.                    foreach (var sortField in ViewBag.ChildGridSortFields)
    100.                    {
    101.                        var sortToAdd = sort.Add(this.ViewBag.ChildItemViewModel.Columns[sortField.Name].ColumnName);
    102.                        if (sortField.SortDirection == DynamicPoint.Office365.CustomerVendorPortal.Common.Models.SortDirection.Descending)
    103.                        {
    104.                            sortToAdd.Descending();
    105.                        }
    106.                        else
    107.                        {
    108.                            sortToAdd.Ascending();
    109.                        }
    110.                    }
    111.                })
    112.                .Read(read => read.Action("ReadChildItems", "Home", this.ViewBag.RouteValues).Data("getChildItemsReadData('#=" + Model.PrimaryKey[0].ColumnName + "#')"));
    113.            })
    114.            .Columns(columnFactory =>
    115.            {
    116.                foreach (DataColumn column in this.ViewBag.ChildItemViewModel.Columns)
    117.                {
    118.                    var c = columnFactory.Bound(column.DataType, column.ColumnName);
    119.                    c.Title(column.Caption);
    120.                    if (column.DataType == typeof(DateTime))
    121.                    { c.Format("{0:d}"); }
    122.                    if (column.DataType == typeof(Boolean))
    123.                    {
    124.                        c.HtmlAttributes(new { style = "text-align: center" }).ClientTemplate("<input type='checkbox' disabled='disabled' " + "# if (" + column.ColumnName + ") { #" + "checked='checked'" + "# } #" + "/>");
    125.                    }
    126.                    if (column.DataType == typeof(Int32))
    127.                    {
    128.                        c.HtmlAttributes(new { style = "text-align: right" });
    129.                        c.HeaderHtmlAttributes(new { style = "text-align: right" });
    130.                    }
    131.                    if ((column.DataType == typeof(Decimal)) || (column.DataType == typeof(float)))
    132.                    {
    133.                        c.HtmlAttributes(new { style = "text-align: right" }).Format("{0:n}");
    134.                        c.HeaderHtmlAttributes(new { style = "text-align: right" });
    135.                    }
    136.                }
    137.                if (ViewBag.DetailsFormEnabled)
    138.                {
    139.                    columnFactory.Template(@<text></text>).ClientTemplate("#= serviceChildResultCommands(data) #");
    140.                }
    141.            })
    142.            .Events(ev => ev.DataBound("onGridDataBound"))
    143.            .Sortable()
    144.            .ToClientTemplate()
    145.)
    146.</script>

     

    Here is the code for the client templates for the buttons:

    1.<script id="service-result-commands-template" type="text/x-kendo-template">
    2.    <button type="button" role="button" class="k-button k-button-icontext" data-dp-recordId="#=Annotations_Id_Key_Only#" onclick="navigateToDetailsForm(this)"><span class="k-icon k-i-edit"></span>View / Edit</button>
    3.</script>
    4. 
    5.<script id="service-child-result-commands-template" type="text/x-kendo-template">
    6.    <button type="button" role="button" class="k-button k-button-icontext" data-dp-recordId="" onclick="navigateToDetailsForm(this)"><span class="k-icon k-i-edit"></span>View / Edit</button>
    7.</script>

     

    Here is the code for my javascript functions:

    01.function serviceResultCommands(model) {
    02.    debugger;
    03.    return kendo.Template.compile($('#service-result-commands-template').html())(model);
    04.}
    05. 
    06.function serviceChildResultCommands(model) {
    07.    debugger;
    08.    return kendo.Template.compile($('#service-child-result-commands-template').html())(model);
    09.}

     

    When I try to expand the details grid I get this error (it fails on line 08 in the above shippet):

    Uncaught SyntaxError: Invalid or unexpected token at eval (<anonymous>) ...

    The code is the same for the master and the details grid, but it only fails when the details grid is expanded and no data is rendered in that grid. It looks like the compile functions completes without error but then it fails on the next call.

    I'm also attaching a screen shot of the error.

    Please help!

    Thanks!

    Kiril

     

     

  2. Preslav
    Admin
    Preslav avatar
    280 posts

    Posted 21 Dec 2017 Link to this post

    Hello Kiril,

    Thank you for providing the code and the error.

    I examined the code and tested the scenario, unfortunately, I was not able to understand what might be causing this faulty behavior. Having said that, could you please prepare and share a sample runnable project that clearly replicates and isolates the issue? I will debug this project locally and this will help me to fully understand the case, after that, I might be able to eventually provide a workaround/fix for the issue.

    I look forward to hearing from you.


    Regards,
    Preslav
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Kiril
    Kiril avatar
    4 posts
    Member since:
    Jun 2016

    Posted 21 Dec 2017 in reply to Preslav Link to this post

    Hi Preslav,

    Thank you very much for looking into my problem!

    I will try to prepare a standalone project, but due to my heavy workload before Christmas holidays that might take a while.

    Anyway, do you think the approach to add the button to the details grid is ok? And there is just something I'm not doing right, not that the approach in general is not correct?

     

    Thanks and Happy holidays!

    Kiril

  4. Preslav
    Admin
    Preslav avatar
    280 posts

    Posted 21 Dec 2017 Link to this post

    Hello again,

    During my investigation today, I checked the provided code and generally speaking, it looks okay to me.

    Personally, for a column that has only a button in it, I would have used a custom command column. An example of this approach is available in this demo:
    Further, to add icons to a custom command, I would suggest following the approach outlined here:
    Please, take your time for creating the example and do not hurry.

    Happy Holidays!


    Regards,
    Preslav
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  5. Kiril
    Kiril avatar
    4 posts
    Member since:
    Jun 2016

    Posted 10 Jan in reply to Preslav Link to this post

    Hi,

    please find attached a demo project that demonstrates the problem. Please do not mind the name of the project and the solution - they were intended for a different problem ..

    As soon as you run the project and expand any of the rows in the grid you will get the error in the browser console.

    Regards,

    Kiril

  6. Answer
    Preslav
    Admin
    Preslav avatar
    280 posts

    Posted 12 Jan Link to this post

    Hello Kiril,

    Thank you for sharing the project. I was able to replicate the problem.

    The reason for this behavior comes from the fact that there is a template inside the detail template. The special character hash(#) is breaking the logic as it stops the main template instead of starting the nested one. More information about this is available in the Overview article of the templates:
    The correct syntax should be:

    columns.Template(@<text></text>).ClientTemplate("\\#= serviceChildResultCommands(data) \\#");

    Additionally, I noticed that the name(.Name('')) of the child grids template is a hardcoded string. This is not a good practice as every child grid will have the same ID. To overcome this, use an approach similar to the one outlined in the "Hierarchy" demo:
    I hope this helps.


    Regards,
    Preslav
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  7. Kiril
    Kiril avatar
    4 posts
    Member since:
    Jun 2016

    Posted 3 days and 15 hours ago in reply to Preslav Link to this post

    Hi Preslav,

    Thank you so much, works like a charm!

    Regards,

    Kiril

Back to Top