Checkbox on html page

Hi,
I understand there is a ready made dashboard on node red,
but to start - I don't want to use this, I'd like to my own simple html page , with a checkbox.

Below is my json:

I can see the html loads and my checkbox ( slider) appears to work ...

I'd like to get a dynamic output into my flow ( for a start to a debug message) that tells me when the checkbox is checked/unchecked) ..
I've tried setting and sending the payload using the javascript inside the html so that it is sent to the debug flow

I'm a real novice at this .. so apologies in advance , but I cant figure out how to set the payload to the checkbox state.
Is it possible and whats the best method to do this.

thanks

[{"id":"1e048a02.f47d96","type":"tab","label":"html1","disabled":false,"info":""},{"id":"f613dcc8.7b4f","type":"http in","z":"1e048a02.f47d96","name":"","url":"bg1","method":"get","upload":false,"swaggerDoc":"","x":120,"y":340,"wires":[["2e46aa3c.238fa6"]]},{"id":"2e46aa3c.238fa6","type":"template","z":"1e048a02.f47d96","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n<style>\n    .switch {position: relative; display: inline-block; width: 120px; height: 68px} \n  .switch input {display: none}\n .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}\n .slider:before {position: absolute; content: \"\"; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}\ninput:checked + .slider {\n  background-color: #2196F3;\n}\ninput:focus + .slider {\n  box-shadow: 0 0 1px #2196F3;\n}\n input:checked+.slider {background-color: #2196F3}\n input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}\n\n/* Rounded sliders */\n.slider.round {\n  border-radius: 34px;\n}\n\n.slider.round:before {\n  border-radius: 50%;\n}\n</style>\n</head>\n<body>\n\n<h2>Toggle Switch</h2>\n <label class=\"switch\">\n <input type=\"checkbox\" id=\"myCheck\" onclick=\"read_checkbox()\">\n  <span class=\"slider round\"></span>\n  <p id=\"text\" style=\"display:none\">Checkbox is CHECKED!</p>\n</label> \n\n<script>\n\nfunction read_checkbox() {\n\n  // Get the checkbox\n  var checkBox = document.getElementById(\"myCheck\");\n\n  // If the checkbox is checked, display the output text\n  if (checkBox.checked == true){\n  console.log(\"Switch is ON\");\n  } else {\n     console.log(\"Switch is off\");\n  }\n}\n</script>\n</body>\n</html>","output":"str","x":360,"y":340,"wires":[["10097ab5.9f5a85","af0ef541.75c348"]]},{"id":"af0ef541.75c348","type":"debug","z":"1e048a02.f47d96","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":610,"y":180,"wires":[]},{"id":"10097ab5.9f5a85","type":"http response","z":"1e048a02.f47d96","name":"","statusCode":"","headers":{},"x":610,"y":340,"wires":[]}]
function read_checkbox() {

  // Get the checkbox
  var checkBox = document.getElementById("myCheck");

  // If the checkbox is checked, display the output text
  if (checkBox.checked == true){
  console.log("Switch is ON");
// the line below doesn't work 
msg.payload = "Switch is on"
  } else {
     console.log("Switch is off");
// the line below doesn't work 
msg.payload = "Switch is off"
  }
}

Hi @bgengine

In your current flow, you have created a HTTP flow that returns the contents of the Template node to the browser when it accesses that page.

There is no on-going connection between the Node-RED flow and the page loaded into the browser. In order to send events back from the page to a Node-RED flow, you need to create a flow to handle that.

For example, you could create another HTTP flow that can be called whenever the checkbox state is changed. You'd also need to add the necessary JavaScript onto the page in order to call that other flow at the right time.

Another option is to create a WebSocket connection from your page back to a Node-RED flow (using the WebSocket listener node). You can then send and receive events to and from the page. But again, you'd need to write the javascript that runs on the page to handle all of that.

This is one of the things Dashboard does for you - it creates the underlying websocket connection to deal with sending events between the page and the flows in Node-RED.

If you don't want to go down the Dashboard route, there is also things like https://flows.nodered.org/node/node-red-contrib-uibuilder that provides a connection between the flows and a webpage, but lets you create a much more custom webpage.

There is a very simple example of a standalone page with a websocket here

Many thanks knolleary,

what you said makes sense now ,

the following does what I need now ,

thanks

[{"id":"1e048a02.f47d96","type":"tab","label":"html1","disabled":false,"info":""},{"id":"f613dcc8.7b4f","type":"http in","z":"1e048a02.f47d96","name":"","url":"bg1","method":"get","upload":false,"swaggerDoc":"","x":120,"y":80,"wires":[["2e46aa3c.238fa6"]]},{"id":"2e46aa3c.238fa6","type":"template","z":"1e048a02.f47d96","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n<style>\n    .switch {position: relative; display: inline-block; width: 120px; height: 68px} \n\n  .switch input {display: none}\n .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}\n\n .slider:before {position: absolute; content: \"\"; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}\n\ninput:checked + .slider {\n  background-color: #2196F3;\n}\n\ninput:focus + .slider {\n  box-shadow: 0 0 1px #2196F3;\n}\n\n input:checked+.slider {background-color: #2196F3}\n    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}\n\n/* Rounded sliders */\n.slider.round {\n  border-radius: 34px;\n}\n\n.slider.round:before {\n  border-radius: 50%;\n}\n</style>\n</head>\n<body>\n\n<h2>Toggle Switch</h2>\n\n <label class=\"switch\">\n<!--  <input type=\"checkbox\" onclick='handleClick(this);' />-->\n    <input type=\"checkbox\" name=\"email\" onclick='toggleCheckbox2(this);' />\n  <span class=\"slider round\"></span>\n  \n \n</label> \n\n<script>\nfunction handleClick(cb) {\n \n  console.log( \"Clicked, new value = \" + cb.checked);\n}\n\nfunction toggleCheckbox2(element) {\n   \n    const params = {\n            Switch_ON: element.checked\n        }\n        const http = new XMLHttpRequest()\n        http.open('POST', 'bg1/')\n        http.setRequestHeader('Content-type', 'application/json')\n        http.send(JSON.stringify(params)) // Make sure to stringify\n        http.onload = function() {\n            alert(http.responseText)\n        }\n    \n    \n}\n\n</script>\n\n</body>\n</html> ","output":"str","x":360,"y":80,"wires":[["10097ab5.9f5a85"]]},{"id":"10097ab5.9f5a85","type":"http response","z":"1e048a02.f47d96","name":"","statusCode":"","headers":{},"x":610,"y":80,"wires":[]},{"id":"c16f9c22.6686","type":"http in","z":"1e048a02.f47d96","name":"","url":"/bg1","method":"post","upload":false,"swaggerDoc":"","x":120,"y":200,"wires":[["1aa947c4.5bba28","ab7e0e7c.fd822"]]},{"id":"ab7e0e7c.fd822","type":"json","z":"1e048a02.f47d96","name":"","property":"payload","action":"","pretty":false,"x":340,"y":160,"wires":[["c42fc35c.b8988"]]},{"id":"c42fc35c.b8988","type":"function","z":"1e048a02.f47d96","name":"return msg.payload to client","func":"msg.payload = 'The msg.payload is : '+msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":530,"y":160,"wires":[["3f3dc8a1.992668"]]},{"id":"3f3dc8a1.992668","type":"http response","z":"1e048a02.f47d96","name":"","statusCode":"","headers":{},"x":800,"y":160,"wires":[]},{"id":"1aa947c4.5bba28","type":"debug","z":"1e048a02.f47d96","name":"/bg1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":330,"y":240,"wires":[]}]

Or you could use uibuilder that does things slightly differently but gives you a websocket connection built in.

thanks Totallyinformation and dceejay,

yes, I understand the uibuilder and dashboard switch are readily available but as a project I was hoping to do his my self and educate my self in the process.

In my new / modified flow I'm connecting to mqtt broker and I can now successfully turn on/off an led on a esp8266.
My problem now is when I load the the web page it needs it to reflect the current status of the led...but it always shows the slider in the off position when I load the page, there after it is ok.
I setup a mqtt command that returned the status of the led from the esp8266..
I think I now need to send this command when I load/ refresh the html page and use the result to update the html page ...

but I dont know how to do this .. and how do I get this value back into the html to set the state of the switch.
I understand I'm probably reinventing the wheel here .. but I find it's a process I find very useful as I end up learning so much ..

any ideas on how I could do this ?

thanks

[{"id":"bdfbf205.c6c11","type":"tab","label":"my_page_mqtt_1","disabled":false,"info":""},{"id":"a5339705.72d688","type":"mqtt out","z":"bdfbf205.c6c11","name":"esp_set_switch","topic":"esp/led_control","qos":"","retain":"","broker":"ff36cbef.2d0788","x":1240,"y":260,"wires":[]},{"id":"9196211e.3119e","type":"mqtt in","z":"bdfbf205.c6c11","name":"esp_recieving led ","topic":"esp/led_control","qos":"2","datatype":"auto","broker":"ff36cbef.2d0788","x":200,"y":360,"wires":[["764a75f8.57690c"]]},{"id":"bd473262.69b5d","type":"switch","z":"bdfbf205.c6c11","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"true","vt":"str"},{"t":"cont","v":"false","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":850,"y":280,"wires":[["68ab541f.33b7dc"],["43258d2e.4fdde4"]]},{"id":"68ab541f.33b7dc","type":"change","z":"bdfbf205.c6c11","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1020,"y":260,"wires":[["a5339705.72d688","311e8838.21e688"]]},{"id":"43258d2e.4fdde4","type":"change","z":"bdfbf205.c6c11","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"OFF","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1020,"y":320,"wires":[["a5339705.72d688","311e8838.21e688"]]},{"id":"d7d0728d.f8f3b","type":"http in","z":"bdfbf205.c6c11","name":"","url":"bg1","method":"get","upload":false,"swaggerDoc":"","x":240,"y":120,"wires":[["f70bec7b.61624"]]},{"id":"f70bec7b.61624","type":"template","z":"bdfbf205.c6c11","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n<style>\n.switch {position: relative; display: inline-block; width: 120px; height: 68px} \n.switch input {display: none}\n.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}\n\n.slider:before {position: absolute; content: \"\"; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}\n\ninput:checked + .slider {\n  background-color: #2196F3;\n}\n\ninput:focus + .slider {\n  box-shadow: 0 0 1px #2196F3;\n}\n\ninput:checked+.slider {background-color: #2196F3}\ninput:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}\n\n/* Rounded sliders */\n.slider.round {\n  border-radius: 34px;\n}\n\n.slider.round:before {\n  border-radius: 50%;\n}\n</style>\n</head>\n<body>\n\n<h2>Toggle Switch</h2>\n\n <label class=\"switch\">\n    <input type=\"checkbox\" name=\"email\" onclick='toggleCheckbox2(this);' />\n  <span class=\"slider round\"></span>\n</label> \n\n<script>\nfunction handleClick(cb) {\n \n  console.log( \"Clicked, new value = \" + cb.checked);\n}\n\nfunction toggleCheckbox2(element) {\n   \n    const params = {\n            switch: element.checked\n        }\n        const http = new XMLHttpRequest()\n        http.open('POST', 'bg1/')\n        http.setRequestHeader('Content-type', 'application/json')\n        http.send(JSON.stringify(params)) // Make sure to stringify\n        http.onload = function() {\n       //  <!--   alert(http.responseText) -->\n        }\n\n}\n\n</script>\n\n</body>\n</html> ","output":"str","x":460,"y":120,"wires":[["e1be4f82.e9c3f"]]},{"id":"e1be4f82.e9c3f","type":"http response","z":"bdfbf205.c6c11","name":"","statusCode":"","headers":{},"x":730,"y":120,"wires":[]},{"id":"daba3198.4477d","type":"http in","z":"bdfbf205.c6c11","name":"","url":"bg1","method":"post","upload":false,"swaggerDoc":"","x":240,"y":240,"wires":[["2f65d629.94052a"]]},{"id":"2f65d629.94052a","type":"json","z":"bdfbf205.c6c11","name":"","property":"payload","action":"","pretty":false,"x":450,"y":240,"wires":[["e6995e26.a6ed8"]]},{"id":"e6995e26.a6ed8","type":"function","z":"bdfbf205.c6c11","name":"return msg.payload to client","func":"msg.payload = 'The msg.payload is : '+msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":640,"y":240,"wires":[["6e7c39f.2f76dc8","bd473262.69b5d"]]},{"id":"6e7c39f.2f76dc8","type":"http response","z":"bdfbf205.c6c11","name":"","statusCode":"","headers":{},"x":890,"y":200,"wires":[]},{"id":"764a75f8.57690c","type":"switch","z":"bdfbf205.c6c11","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"true","vt":"str"},{"t":"cont","v":"false","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":410,"y":360,"wires":[["7860b8b3.86bc38"],["7860b8b3.86bc38"]]},{"id":"7860b8b3.86bc38","type":"debug","z":"bdfbf205.c6c11","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":360,"wires":[]},{"id":"1bda936e.6c9dbd","type":"mqtt in","z":"bdfbf205.c6c11","name":"esp_recieving status","topic":"esp/status_s","qos":"2","datatype":"auto","broker":"ff36cbef.2d0788","x":210,"y":480,"wires":[["688e5a78.e9cfe4"]]},{"id":"688e5a78.e9cfe4","type":"debug","z":"bdfbf205.c6c11","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":490,"y":480,"wires":[]},{"id":"311e8838.21e688","type":"mqtt out","z":"bdfbf205.c6c11","name":"esp_status_request","topic":"esp/status_req","qos":"","retain":"","broker":"ff36cbef.2d0788","x":1250,"y":320,"wires":[]},{"id":"ff36cbef.2d0788","type":"mqtt-broker","name":"127.0.0.1","broker":"127.0.0.1","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

When the browser loads up your page and sets up the web socket then the server can receive a message on websocket in node which can then use to trigger an initialisation of whatever you like.

You will find an example on the uibuilder WIKI that talks about caching which is what you might want to think about. There is no connection between the client and the server when the client first loads unless you include some default data in the template (which is in fact possible with Node-RED since your template can be data driven). In uibuilder, you create your master page as an empty template typically and then on first load (which the client sends a msg to Node-RED so that it knows a new client has loaded), you can send a cache dump of data to the client.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.