MagicMirror Forum

    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • Donate
    • Discord
    MagicMirror² v2.24.0 is available! For more information about this release, check out this topic.

    Nunjucks and Chartjs / Javascript

    Development
    2
    15
    2230
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • lavolp3
      lavolp3 Module Developer last edited by

      Can anyone help me placing a chartjs graph in a nunjucks template?

      Using the usual JS it was problem for me.
      I would use the getDom method and create the relevant divs and a canvas and later on place the chart using the described chart.js method which looks like this:

      var myChart = new Chart(context, { options })
      

      With a Nunjucks template I have my problems.
      I had an empty canvas element in the template and tried to draw a graph in the JS part but it disappears after a very short time again. I have the suspicion the canvas gets “overwritten” by template updates.

      Then I tried to create the canvas element itself on foot (document.createElement) in the function that creates the graph but it turns out that apparently the containing div is not even created. At least by calling document.getElementById inside the function I get “null”

      When does Nunjucks create the document objects?
      And if it does, does it overwrite any nodes created using a javascript function?

      If I am reliant on Javascript to create a document object (like here), do I need to stuff this into a filter or is there another way to manipulate the DOM?

      Hope my problem is comprehensible.

      Thanks!

      How to troubleshoot modules
      MMM-soccer v2, MMM-AVStock

      S 1 Reply Last reply Reply Quote 0
      • S
        sdetweil @lavolp3 last edited by sdetweil

        @lavolp3 according to the code in app/js/module.js

        its either template OR dom, not both.

        	/* getDom()
        	 * This method generates the dom which needs to be displayed. This method is called by the Magic Mirror core.
        	 * This method can to be subclassed if the module wants to display info on the mirror.
        	 * Alternatively, the getTemplate method could be subclassed.
        

        using Chart.js in my module I do

           				position: 'top_right',
        

        in config, so that is the base location
        then

        create the canvas div, and then the chart in the canvas (I could have multiple charts to draw, from an array of data)

        					var this_pin = wself.config.Pins[pin_index];
        					// clear the work variable
        					var canvas = null;
        					// try to locate the existing chart
        					if ((canvas = document.getElementById("myChart" + this_pin)) == null) {
        						var c = document.createElement("div");
        						c.style.width = wself.config.width + "px";
        						c.style.height = wself.config.height + "px";
        						if (!wself.config.stacked)
        						{c.style.display = "inline-block";}
        						wself.wrapper.appendChild(c);
        
        						canvas = document.createElement("canvas");
        						canvas.id = "myChart" + this_pin;
        						c.appendChild(canvas);
        					}
        					// if the chart has been created
        					if (wself.charts[pin_index] != null) {
        						// destroy it, update doesn't work reliably
        						wself.charts[pin_index].destroy();
        						// make it unreferenced
        						wself.charts[pin_index] = 0;
        					}
        					// create it now
        					wself.charts[pin_index] = new Chart(canvas, {
        						type: "line",
        						showLine: true,
        						data: {
        ...
                    // then return the outer container div 
        		return wself.wrapper;
        

        U could download my module and look at it
        https://github.com/sdetweil/WaterLevels

        so, in the end I have

        wrapper  (div)
             div (chart 1)
               chart canvas
             div (chart 2)
               chart canvas
             ...
             div (chart n)
               chart canvas
        

        I have never used templates for anything… (I have enough trouble with normal code)

        Sam

        Create a working config
        How to add modules

        lavolp3 2 Replies Last reply Reply Quote 1
        • lavolp3
          lavolp3 Module Developer @sdetweil last edited by

          @sdetweil

          Thanks Sam.
          I have built a module with chart.js as well, no problme with that, however this time I am kind of dependant on nunjucks because I had forked a project and do not want to rebuild everything.

          But thanks for pointing me to the core code. I always forget to have a look into that.

          How to troubleshoot modules
          MMM-soccer v2, MMM-AVStock

          1 Reply Last reply Reply Quote 0
          • lavolp3
            lavolp3 Module Developer @sdetweil last edited by

            @sdetweil said in Nunjucks and Chartjs / Javascript:

            its either template OR dom, not both.
            /* getDom()

            • This method generates the dom which needs to be displayed. This method is called by the Magic Mirror core.
            • This method can to be subclassed if the module wants to display info on the mirror.
            • Alternatively, the getTemplate method could be subclassed.

            I understand this differently from the core code.
            From what I see getDom is the parent function and getTemplate fills this with html code from a template. So in a module using nunjucks you could call getDom AND getTemplate separately.
            And manipulate the dom after the template is loaded.
            But that is something I fail to do…

            How to troubleshoot modules
            MMM-soccer v2, MMM-AVStock

            S 1 Reply Last reply Reply Quote 0
            • S
              sdetweil @lavolp3 last edited by sdetweil

              @lavolp3 note… if you have the functions getDom, and getTemplate and getTemplateData
              then the core methods will NOT be called.

              i think IF you have getDom , then unless YOU call them , getTemplate and getTemplateData will NOT be called. (because u replaced the built in getDom() with your own version)

              getTemplate and getTemplateData are ONLY called from the default getDom

              I confirmed this in one of my modules that uses getDom()… I added the template methods, and logged when they were called…

              getTemplate: function() {
              	Log.log("in getTemplate");
              	return "";
              },
              getTemplateData: function (){
              	Log.log("in getTemplateData");
              	return "";
              }
              

              they were not called

              Sam

              Create a working config
              How to add modules

              lavolp3 1 Reply Last reply Reply Quote 0
              • lavolp3
                lavolp3 Module Developer @sdetweil last edited by

                @sdetweil fully understood and agree.
                Thinking about replacing getdom with the native one and somehow implementing my chart function but there has to be a simpler way.

                After all getdom is the only function replacing the dom, in my case loading the template, isn’t it?. So there must be a way to manipulate the dom directly after it has been created.

                How to troubleshoot modules
                MMM-soccer v2, MMM-AVStock

                lavolp3 1 Reply Last reply Reply Quote 0
                • lavolp3
                  lavolp3 Module Developer @lavolp3 last edited by

                  Wait. There is an asynch function in the getdom function, isn’t there? So calling my function directly afterwards may lead to a state where the dom is not yet created. Hmm…

                  How to troubleshoot modules
                  MMM-soccer v2, MMM-AVStock

                  S 1 Reply Last reply Reply Quote 0
                  • S
                    sdetweil @lavolp3 last edited by

                    @lavolp3 the dom is created way back at the beginning when u receved the DOM_OBJECTS_CREATED notification… so, when your module is called later, the DOM exists… document. exists

                    YOUR contribution to the dom may not be there for some time after your getDom() routine returns. MM does not specify how long…

                    if I need to fiddle with the dom directly, I usually do that thru a time routine, set for 1-2 seconds after getdom returns.

                    Sam

                    Create a working config
                    How to add modules

                    lavolp3 1 Reply Last reply Reply Quote 0
                    • lavolp3
                      lavolp3 Module Developer @sdetweil last edited by

                      @sdetweil
                      Sam, thanks again for your valuable contribution.
                      I tried to meddle with the getdom function, which does not work because the returned module div is appended to a parent node somewhere else in the MM code hierarchy. And only then I can refer to the DOM elements. (I guess that’s what you meant and I haven’t understood).

                      So, although I didn’t like it, I kind of did it your way and included a 3-second setTimeout() call directly after the updateDom() call, in which I called my chart function.

                                          self.updateDom(self.config.animationSpeed);
                                          setTimeout (function() {
                                            self.createBarChart(...);
                                          }, 3000);
                      
                      

                      It works now.
                      I still don’t like it. 🙂
                      But I want to move on.

                      How to troubleshoot modules
                      MMM-soccer v2, MMM-AVStock

                      S 1 Reply Last reply Reply Quote 0
                      • S
                        sdetweil @lavolp3 last edited by

                        @lavolp3 said in Nunjucks and Chartjs / Javascript:

                        I tried to meddle with the getdom function, which does not work because the returned module div is appended to a parent node somewhere else in the MM code hierarchy. And only then I can refer to the DOM elements. (I guess that’s what you meant and I haven’t understood).

                        main.js

                        	var updateModuleContent = function(module, newHeader, newContent) {
                        		var moduleWrapper = document.getElementById(module.identifier);
                                if (moduleWrapper === null) return;
                        		var headerWrapper = moduleWrapper.getElementsByClassName("module-header");
                        		var contentWrapper = moduleWrapper.getElementsByClassName("module-content");
                        
                        		contentWrapper[0].innerHTML = "";
                        		contentWrapper[0].appendChild(newContent);
                        
                        		if( headerWrapper.length > 0 && newHeader) {
                        			headerWrapper[0].innerHTML = newHeader;
                        		}
                        	};
                        

                        takes the content returned from getDom() and inserts it into the div created by module_id in the dom tree in the ‘position’ specified.

                        in my code that is why i create the div ‘canvas’. I have the div object, in getDom, and can generate the content immediately… no timer waiting to look it up later

                                    canvas = document.createElement("canvas");    // < ---
                                    canvas.id = "myChart" + this_pin;
                                    c.appendChild(canvas);                                           // < ---
                                  }
                                  // if the chart has been created
                                  if (wLself.charts[pin_index] != null) {
                                      // destroy it, update doesn't work reliably
                                      wLself.charts[pin_index].destroy();
                                      // make it unreferenced
                                      wLself.charts[pin_index] = 0;
                                  }
                        					try { 
                        						// create it now
                        						wLself.charts[pin_index] = new Chart(canvas, {   // < ---
                        

                        then getDom() returns the completed chart… no need for build later

                        Sam

                        Create a working config
                        How to add modules

                        lavolp3 1 Reply Last reply Reply Quote 0
                        • 1
                        • 2
                        • 1 / 2
                        • First post
                          Last post
                        Enjoying MagicMirror? Please consider a donation!
                        MagicMirror created by Michael Teeuw.
                        Forum managed by Paul-Vincent Roll and Rodrigo Ramírez Norambuena.
                        This forum is using NodeBB as its core | Contributors
                        Contact | Privacy Policy