How to use another js in mithril.js

280 views Asked by At

I need to include a third-party js library in my website and a working example in plain HTML file is something like

<div id="app"></div>
<script src="app.js"></script>
<script>App.initialize();</script>

Basically the initialize() function will first fill the #app with a loading animation then fetch data from external API and finally load the #app with html code it generated.

Everything works fine until I rewrite it in mithril.js, something like

const page = {
  view: () => [
    m('script', {src: 'app.js'}),
    m(app)
  ]
} 
const app = {
  oncreate: () => { App.initialize();},  
  view: () => m('#app')
}

When I render the page, I can still see the loading animation but after it is gone, nothing shows up in #app. The expected code is not loaded in #app as in plain HTML file, and there is no error message in the console.

Did I miss anything or do anything wrong in mithril.js?

1

There are 1 answers

0
Ian Wilson On

I think there might be some sort of timing issue with loading the script that way. Also if it puts things into the body element then mithril might re-render over it. Maybe try something like this:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf8">
    </head>
    <body>
        <script src="https://unpkg.com/mithril/mithril.js"></script>
        <div id="page"></div>
        <script type="text/javascript">
         let appLoaded = false;
         let mithrilLoaded = false;
         let appTimer = null;
         let mithrilTimer = null;
         function stopSync() {
             console.log('Sync done, init app.')
             appLoaded = mithrilLoaded = true;
             window.clearInterval(appTimer);
             window.clearInterval(mithrilTimer);
             appTimer = mithrilTimer = null;
             App.initialize();
         }
         function startAppSync() {
             console.log('App loaded, start sync with mithril.')
             appLoaded = true;
             appTimer = window.setInterval(checkAppSync, 100);
         }
         function startMithrilSync() {
             console.log('Mithril loaded, start sync with app.')
             mithrilLoaded = true;
             mithrilTimer = window.setInterval(checkMithrilSync, 100);
         }
         function checkAppSync() {
             console.log('Checking mithril from app sync.')
             if (mithrilLoaded) {
                 stopSync();
             }
         }
         function checkMithrilSync() {
             console.log('Checking app from mithril sync.')
             if (appLoaded) {
                 stopSync();
             }
         }
         const page = {
             view: function() {
                 return m('', [
                     m('script', {
                         onload: function () {
                             startAppSync();
                         },
                         src:'app.js'
                     }),
                     m(app),
                 ]);
             }
         }
         const app = {
             oncreate: function() {
                 startMithrilSync();
             },
             view: function() {
                 return m('#app');
             }
         }

         m.mount(document.getElementById('page'), page);
        </script>
    </body>
</html>

More information here, the scripts injected are loaded async by default. You can test this in browser with document.createElement('script').async.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement#dynamically_importing_scripts