Mustache templates, PHP json_encode, Javascript arrays, and html entities

Mustache templates, PHP json_encode, Javascript arrays, and html entities

by A Guy -
Number of replies: 8

I had some working code where I used html_writer in Moodle. I wanted to pull that out and use a Moodle template with $OUTPUT->render_from_template() and my new mustache template.


Errors started showing up as the browser complains about "SyntaxError: expected expression, got '&'". The problem is that I am creating an array of label names and converting it to a json string via json_encode to pass to a JQuery parameter but Moodle appears to be using htmlspecialcharacters() when I use render_from_template() on the json string. So the browser sees [{&quote;mylabel1&quote;,. . .  and doesn't know what to do with it.


I have tried several of the json_encode second parameter options like JSON_UNESCAPED_UNICODE. They don't correct the issue. I've tried just passing in an array created by PHP. I've tried manually creating a string which doesn't work. I get the wrong escaped literal message or that the second parameter is an array when it should be a string error messages.


So how do I accomplish this?

Here is the wrong rendering

hints: ["my course label 1","my course label 2","my course label 3","my course label 4 ","my course label 5"],

I need one of the following outputs:

hints: ['my course label 1','my course label 2','my course label 3','my course label 4 ','my course label 5'],

or

hints: ["my course label 1","my course label 2","my course label 3","my course label 4 ","my course label 5"],
       

Average of ratings: -
In reply to A Guy

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by Mark Johnson -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

If I understand correctly, you have an array in PHP which you want to make available in Javascript, and you're trying to achieve this by JSON-encoding the array and outputting it in your template?  Presumably something like:

<script>var = {{ myarray }};</script>

If you want to output a raw string without escaping in a mustache template, you can use {{{ triple braces }}} instead of {{ double }}.  This may achieve what you want.

However, another tidier approach would be to move your javascript code to an AMD module, then call it with $PAGE->requires->js_amd_call().  You can pass your array as an argument to that function, which will then be correctly translated and passed to your javascript code.

Average of ratings: Useful (1)
In reply to Mark Johnson

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by A Guy -

Thank you Mark. You were correct sending it over as a string with the curly braces solved that problem.


Now there is unfortunately another issue.


I am getting a "TypeError: $(...).raty is not a function" error.

The top of my JS is

{{#js}}                             
$(function() {
$('#{{my_style_id}}').raty({

....

I am using JQuery and using raty.

Is the error because I have to do something specific to call the raty plugin js file? I call them with Javascript tags at the top of the template. And I see them on the page in the code.

Or is it because I need to load Jquery in the template in some particular way? I looked at the Moodle docs and saw

define(['jquery'], function($) {

. . .


So I wrapped my functions that way:

require(['jquery'], function($) {
$('#{{my_style_id}}').raty({

....


I even tried

require(['jquery'], function($) {
  JQuery('#{{my_style_id}}').raty({

....


Not working.


In reply to A Guy

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by Mark Johnson -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

require(['jquery'], function($) {
    $('#{{my_style_id}}').raty({

That code will load jquery as an AMD module, and make it available within your function as the variable $.  However, it wont load the raty plugin as well.  It doesn't look like raty is packaged as an AMD module, which makes it tricky to load it in this way.

You could look up loading jquery plugins using a requireJS shim (I've not done this myself).  Otherwise another developer who has worked with jquery plugins might be able to advise.

Edit: This post might give you some clues: https://moodle.org/mod/forum/discuss.php?d=375604&parent=1516459


In reply to Mark Johnson

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by A Guy -

Thanks Mark for your help here. I had the code working with html_writer already. I just wanted to convert it to templates as I was asked to. Of course it is easier to style/theme when you have the presentation logic separated from the business/backend logic . . .aka templates. But it appears this is just too tricky right now. My code is working in a non-templated fashion. So I am OK. It just seems that the templating needs to be finessed or I need to learn it better. Having to convert an array to a string seems weird to me. . . despite all of these other hurdles. sad

In reply to A Guy

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by Mark Johnson -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

The idea is that you shouldn't have to convert your array to a string, if you write your javascript as an AMD module and load it with js_amd_call() then you keep your javascript and its data completely separate to your template and avoid the issue.  The only reason I can think of to include the javascript in the template itself is if you want to allow it to be overridden by a theme.

In reply to Mark Johnson

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by A Guy -

No need to get into a debate about including JS or CSS in a file or call it externally or use a template or not. That has been argued to death as far I know.


I have working code using html_writer. And it is staying that way given I now have to rewrite/compile someone else's JS (ie Raty) just to satisfy a purist's MVC wants.


But thanks for your help.

Average of ratings: Useful (1)
In reply to Mark Johnson

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by Eduardo de Vila -
Thank you so much Mark, you just save my life 😃
In reply to A Guy

Re: Mustache templates, PHP json_encode, Javascript arrays, and html entities

by jack miller -

You can use htmlspecialchars_decode() PHP's default function while getting output.

I think this will help