Skip to content

JS: how to transfer data from HTML to JS

Benjamin RICHARD edited this page May 15, 2018 · 2 revisions

In old application, HTML is built by the backend (PHP, Java,...). But those applications also use Javascript to allow more interaction on the frontend. Often, we need to transmit data from the webpage to the Javascript. You may want to do Ajax request to perform this, but it will increase the render time, so the user will have to wait more seconds for the application. So if you want the application to be available in a quickest way, you will certainly embed some datas in the HTML like this:

<script>
  var companiesId = [{{ $companiesId.implode(',') }}]; // which will render [1,5,6,15,32] with $companiesId = [1,5,6,15,32] in PHP
</script>
<script src='/js/my-app.js'></script>

/**
// my-app.js may look like this (so it autorun the content of the script when it's loaded):
console.log('debug purpose of companies', companiesId);
*/

This works, but in fact you are injecting variable in the global context (indeeed window). So your script my-app rely on those global variable. So what will happens if different scrpits relies on them and alter them ? There is a huge risk of regression.

Using pure Javascript, i prefer to use Events to propagate data from the main HTML to the scripts. Imagine your script as an API and the variables you want to send to it like the signature of the API. The only thing is to prevent the script to autorun anything else but the listener.

<script>
  // it's still in the global scope, but you can wrap it in a pseudo namespace like this
  var myApp = {
    eventInitCollaboratorApp: new CustomEvent('init-companies-app', {
      detail: {
        ids: [{{ $companiesId.implode(',') }}]
      }
    })
  }
</script>
<script src='/js/my-app.js' onload="javascript:document.querySelector('body').dispatchEvent(myApp.eventInitCollaboratorApp);"></script>

/**
// my-app.js may look like this (so it autorun the content of the script when it's loaded):
document.querySelector('body').addEventListener('init-companies-app', function(ev) {
  run(ev.detail.ids);
})

const run = function(companiesId) {
  console.log('debug purpose of companies', companiesId);
}
*/

If you need to support <IE10 you might need this polyfill to import at the beginning (the best would be in a script tag inlined in the HEAD):

// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
(function () {

  if ( typeof window.CustomEvent === "function" ) return false;

  function CustomEvent ( event, params ) {
    params = params || { bubbles: false, cancelable: false, detail: undefined };
    var evt = document.createEvent( 'CustomEvent' );
    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
    return evt;
   }

  CustomEvent.prototype = window.Event.prototype;

  window.CustomEvent = CustomEvent;
})();