How to get variables from PHP into javascript AMD modules in M3.5

How to get variables from PHP into javascript AMD modules in M3.5

by Dave Balch -
Number of replies: 7

Hi,

I'm struggling to find my way around the various types of JS in Moodle; I have a load of data (including user HTML) to load into my AMD module - but MDL-49046 says I shouldn't pass massive amounts of data or huge rendered blocks of escaped HTML to the javascript via js_call_amd().

A previous solution for M2.0 points towardsusing  data_for_js(), which has since been deprecated in favour of js_init_call() - but I don't see how to use that with AMD sad

What am I missing?

Edit: After re-reading js_call_amd() guide: "A preferred approach is to pass css selectors for DOM elements that contain data-attributes for any required data, or fetch data via ajax in the background."

  1. I guess I could dump JSON into a hidden element, load it and parse it - seems pretty clunky mixed
  2. I don't want to fetch data via ajax in the background, as it will create more requests and slow the page load.

Cheers,
Dave.


Average of ratings: -
In reply to Dave Balch

Re: How to get variables from PHP into javascript AMD modules in M3.5

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

This is how I do it:

PHP


$someopts['somevar1'] =1234;
$someopts['somevar2']=5678;
$someopts['somevar3']=91011;

//we put the opts in html on the page
//convert opts to json
$jsonstring = json_encode($someopts);
$fetchid = 'someopts_9999';
$opts_html = \html_writer::tag('input', '', array('id' => 'amdopts_' . $fetchid, 'type' => 'hidden', 'value' => $jsonstring));
echo $opts_html;
$opts=array('fetchid'=>$fetchid);
$this->page->requires->js_call_amd("mod_mymod/myamdmodule", 'init', array($opts));


JAVASCRIPT/AMD

init: function(props){
//pick up opts from html
var theid='#amdopts_' + props.fetchid;
var configcontrol = $(theid).get(0);
if(configcontrol){
this.activitydata = JSON.parse(configcontrol.value);
$(theid).remove();
}else{
//if there is no config we might as well give up
log.debug(' No config found on page. Giving up.');
return;
}
}
Average of ratings: Useful (3)
In reply to Justin Hunt

Re: How to get variables from PHP into javascript AMD modules in M3.5

by Dave Balch -

Thanks Justin, I'll take that approach.

It seems surprisingly straight-forward compared to the hoops I've been jumping througth with templates, webservices, and forms using fragment.js - but I'm fine with that! smile

In reply to Dave Balch

Re: How to get variables from PHP into javascript AMD modules in M3.5

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

What is this large amount of data? Difficult to advise on the best way if we don't know what you are trying to achieve.

For displaying HTML, you should be using templates (which need to be fed a relatively small amount of data to generate a lot of HTML). Templates can be rendered in JavaScript as well as in PHP.

If you are doing form auto-complete or something similar, you should be fetching the data using a web service call.

In reply to Tim Hunt

Re: How to get variables from PHP into javascript AMD modules in M3.5

by Dave Balch -

Well, it's large relative to the 1Kb limit on js_call_amd(), but I don't know how large it'll be in production; it's for loading HTML (and metadata) created by students as annotations on an image or map, so it'll probably vary a lot depending on each course and cohort.

My module loads a map, and then the annotations are plotted on the map using the metadata.

Justin's suggestion looks like a good approach that won't incur any extra loads.

Cheers,
Dave.

In reply to Dave Balch

Re: How to get variables from PHP into javascript AMD modules in M3.5

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I would probably do this as follows:

In PHP output HTML like:

<div class="annotatedimage">
  <div class="backgroundimage">
    <img src="...">
  </div>
  <div class="annotations">  <!-- CSS to make this display: none by defauls -->
    <dif class="annotation" data-xpos="123" data-ypos="456">... Content here ...</div>
    <!-- ... more annotation divs -->
  </div>
</div>

Then, the JavaScript does not need any data sent to it separately. Everything you need in the HTML. All the JS needs to do is to move things around.

And, in fact, this is not just a theoretical suggestion. That is basically how qtype_ddimageortext and qtype_ddmarker work.
Average of ratings: Useful (2)
In reply to Tim Hunt

Re: How to get variables from PHP into javascript AMD modules in M3.5

by Dave Balch -

Thanks Tim, that looks like a good approach as well.

There are often lots of different ways to achieve the same goal, and the challenge is then figuring out which one is best - sometimes a joy, sometimes a curse!

I guess just picking one and seeing how it works out has a nice empirical flavour to it smile

Cheers,
Dave.

In reply to Dave Balch

Re: How to get variables from PHP into javascript AMD modules in M3.5

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

"I guess just picking one and seeing how it works out has a nice empirical flavour to it."

Well, it is certainly a great way to learn.