MagicMirror² v2.8.0 is available! For more information about this release, check out this topic.

Module shows no text.



  • Hi everybody! 🙃

    I tried to write a module for the first time. It was supposed to show the menu including the prices of the canteen at our university, but for some reason I don’t get an output. I tried to run the logic and a test module with „hello world“ and both worked. I attached to this message my code and I hope that someone can help me out with this issue.

    Here ist my code:

    Module.register("MMM-Test", {
      defaults: {},
      start: function () {
    	this.count = 0
      	var timer = setInterval(()=>{
        		this.updateDom()
        		this.count++
      		}, 30000) // 1000 = 1s
    	},
      getDom: function() {
        var element = document.createElement("div")
      element.className = "myContent"
        var subElement = document.createElement('table');
        var tr = document.createElement('tr');
        var td1 = document.createElement('td');
        var td2 = document.createElement('td');
        var request = require('request');
        var text1;
        var text2;
        var heute = new Date().toISOString().substr(0,10);
        var cnt = 0;
     request({
        url: 'https://openmensa.org/api/v2/canteens/838/days/'+heute+'/meals',
        json: true
     }, function(error, response, body) {
            element.innerHTML = ('\nCAFETERIA EAH am ' +  heute.substring(8,10)+ '.'+heute.substring(5,7) +'.'+heute.substring(0,4)+':');
    	if (body.length < 1){
    		text1 = document.createTextNode('Heute geschlossen!');
    	}
    	else {
    	  while (body.length > cnt) {
    		text1 = document.createTextNode((body[cnt].name));
    		text2 = document.createTextNode(body[cnt++].prices.employees.toFixed(2) +' €');
    		}
    	}
    });
        td1.appendChild(text1);
        td2.appendChild(text2);
        tr.appendChild(td1);
        tr.appendChild(td2);
        subElement.appendChild(tr);
        subElement.id = "COUNT"
        element.appendChild(subElement)
    return element
    },
      notificationReceived: function() {},
      socketNotificationReceived: function() {},
    })
    
    


  • @k-0 request is an async call, it will return immediately, but the callback function will not happen until a LONG time after the getdom() function returns…

    you need to do this someplace else (on a timer maybe)…

    and when the request returns, then save the data and signal mm with this.updateDom() to indicate new data is ready for viewing… MM will then call your getDom() routine…



  • Can you (or someone else) give me an example? I have no experience with async programming.
    I tried to solve this problem with setTimeout(function() { mycode }, 6000) , but it doesn’t work.


  • Module Developer

    @k-0
    Try this;

    Module.register("MMM-Test", {
      defaults: {},
      start: function () {
        this.count = 0
        this.timer = null
      },
    
      getContent: function() {
        var heute = new Date().toISOString().substr(0,10);
        var cnt = 0;
        var url = 'https://openmensa.org/api/v2/canteens/838/days/' + heute + '/meals'
        fetch(url, {mode:"cors"})
        .then((response) => {
          console.log("Response fetched.")
          return response.text();
        })
        .then((text) => {
          this.parseContent(text)
        })
        .catch((error) => {
          console.log('Error:', error)
        })
    
        this.timer = setTimeout(()=>{
          this.getContent()
        }, 30000)
      },
    
      parseContent: function(text) {
        var dom = document.getElementById("TEST")
        dom.innerHTML = ""
        var data = JSON.parse(text)
        for (let i = 0; i < data.length; i++) {
          var item = data[i]
          var elem = document.createElement("div")
          elem.innerHTML = `${item.category} - ${item.name}`
          dom.appendChild(elem)
        }
      },
    
      notificationReceived: function(noti, payload, sender) {
        if (noti == "DOM_OBJECTS_CREATED") {
          this.getContent()
        }
      },
    
      getDom: function() {
        var dom = document.createElement("div")
        dom.id = "TEST"
        return dom
      }
    })
    
    


  • @Sean doable, but sloppy. Supposed to call updatedDom(), and let mm handle the actual update.


  • Module Developer

    @sdetweil
    Yes, you’re right. it was just an example. Anyway, it can be done like this;

    parseContent: function(text) {
        this.lastPatched = JSON.parse(text)
        this.updateDom()
    },
    
    getDom: function() {
        var dom = document.createElement("div")
        dom.id = "TEST"
        if (this.lastPatched) {
          ... // draw patched data...
        }
        return dom
    }