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

renderInTemplate() forgives to escape # for nested template

4 Answers 640 Views
General Disccussions
This is a migrated thread and some comments may be shown as answers.
Paolo
Top achievements
Rank 1
Paolo asked on 19 Dec 2017, 05:13 PM

HI

I am using renderInTemplate() to nest some widget, in particular, grid inside a window, I discovered the following method is missing to replace # in case the widget is nested inside another and the inner one contains in its definition a template string, so I suggest to patch width in a similar way ( more testing by your side is needed but It permitted to remova a Uncaught Error: Invalid template:' error in my application )

 

     public function renderInTemplate() {
        $this->isClientTemplate = true;
        $output = $this->render();
        $this->isClientTemplate = false;
        $output = str_replace('</script>', '<\\/script>', $output);

        // ADD THIS LINE to Replace also hash to prevent Uncaught Error: Invalid template:'

        return str_replace('#', '\\#', $output);
    }

 

 

4 Answers, 1 is accepted

Sort by
0
Dimitar
Telerik team
answered on 21 Dec 2017, 07:59 AM
Hello Paolo,

Thank you for the feedback provided.

In order to properly handle the # character in a binding expression of a nested template, this character must be escaped with via \\# and this behavior is implemented by design. In this way the character is ignored by the outer template, but is handled correctly by the inner template. This is documented in the official Templates Documentation:


Regards,
Dimitar
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.


0
Paolo
Top achievements
Rank 1
answered on 20 Mar 2018, 11:59 AM

Hi Dimitar, I will try to explain better the problem that I think many others developer could have :

  1. We need to call $grid->renderInTemplate() for a grid that in turn contains some columns with a custom column template
  2. the output from renderInTemplate() must be placed in a script text/x-kendo-template for later use ( es: as content in a kendoWindow )
  3. the stock renderInTemplate() function on Widget php class, only escape the jquery id selector with backslash but it doesn't escape the #s different by the jquery widget id, for example
    1. #s present in a custom template column
    2. #s present in an event handler for a widget set via Widget.prototype.bind() 
  4. In our scenario we render the text/x-kendo-template via kendo.template() , so # left unescaped cause invalid template exception
  5. Your code is useful in scenario like Nested Kendo Grid https://demos.telerik.com/kendo-ui/grid/hierarchy , where you need # left unescape
  6. If you need a complex scenario where some # must be left unescaped a mixed approach should be adopted

Conclusion : it could be useful have another function like the following:

trait HasTemplateRendering
{
    public function renderInTemplateEx($placeholders=[])
    {
        /**
         * + Replace every # not yet escaped
         * + Doesn't replace # preceded or followed by { and } , es: {# or #} are not escaped

         *   and they will be left unescaped

         * + makes a search/replace of placeholders specified in the associative arrays placeholders

         *   at server runtime.

         */
        return self::renderInTemplateImpl($this,$placeholders);
    }
 
    public static function renderInTemplateImpl(Widget $widget,$placeholders=[])
    {      
        $output = $widget->renderInTemplate();
        $output = preg_replace('/(?<!({|\\\\))#(?!})/', '\\#', $output);
        /**
         * Search :placeholders and replace them with their values
         */
        $output = preg_replace_callback('/:([[:alpha:]_][[:alnum:]_]*)/',function($match)use($placeholders){
            return isset($placeholders[$key = $match[1]]) ? $placeholders[$key] : $match[0];
        },$output);
        /**
         * Replace '{#','#}' with #
         */
        return preg_replace(['/({#)|(#})/'],'#',$output);
    }
}

 

0
Accepted
Dimitar
Telerik team
answered on 20 Mar 2018, 12:34 PM
Hello Paolo,

Thank you for sharing your solution with the community. 

I will review it and create a Knowledge Base Article based on the provided extension, so that approach is also available in the official documentation. 

Regards,
Dimitar
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.
0
Paolo
Top achievements
Rank 1
answered on 23 Apr 2018, 09:54 AM
Nice ! thanks
Tags
General Disccussions
Asked by
Paolo
Top achievements
Rank 1
Answers by
Dimitar
Telerik team
Paolo
Top achievements
Rank 1
Share this question
or