I tested it in svelte without uibuilder and it works as I expected, it is definitely something related to how uibuilder handles svelte? However I am unsure.
simply it is only the syntax that is not generating the CSS element in whicheverfile it is supposed to be doing it in. I have read their documentation and I don't think I am misunderstanding anything, but would love to be corrected.
As I said I got it to work by manually doing the CSS file, however it is strange that there is a difference in general.
Here is an example flow with my fix and how it was from the example.
Thank you so much for looking into this with me, uibuilder is awesome!
[
{
"id": "afe95d068c771742",
"type": "tab",
"label": "Flow 2",
"disabled": false,
"info": "",
"env": []
},
{
"id": "e425a6e20ba8c7ed",
"type": "group",
"z": "afe95d068c771742",
"name": "The template example",
"style": {
"fill": "#bfc7d7",
"fill-opacity": "0.31",
"label": true,
"color": "#000000"
},
"nodes": [
"733e217d1f7edab9",
"510ba5174729ba58",
"7d15b868a5a04fe9",
"6d43a3fa23e4b6a1",
"389c413ade10fbab",
"9083ec150141c389",
"2fa24135bc2c67f5",
"b6f1c7d8e58d2770",
"bb67fc0d7d19c966",
"fadf802d93c76823",
"c8747853bc7976e2",
"60aeacf943e5cc5d",
"99ce70c0181b2927"
],
"x": 274,
"y": 139,
"w": 652,
"h": 448
},
{
"id": "60aeacf943e5cc5d",
"type": "group",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "Add/remove dynamic list",
"style": {
"label": true,
"fill": "#ffffff",
"fill-opacity": "0.5",
"color": "#777777"
},
"nodes": [
"04d7537d634caec2",
"3c10deba5a5b82a6",
"ff162c4ee10a16ec"
],
"x": 314,
"y": 439,
"w": 492,
"h": 122,
"info": "Demonstrates that uibuilder's dynamic ui\r\nfeatures work with Svelte."
},
{
"id": "c8747853bc7976e2",
"type": "junction",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"x": 600,
"y": 300,
"wires": [
[
"510ba5174729ba58"
]
]
},
{
"id": "733e217d1f7edab9",
"type": "inject",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "Send a greeting",
"props": [
{
"p": "greeting",
"v": "Hi from Node-RED 😁🚀🎆😎",
"vt": "str"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "A Message From Node-RED",
"x": 400,
"y": 320,
"wires": [
[
"c8747853bc7976e2"
]
],
"info": "Send a simply msg to the front-end.\r\n\r\nThe default front-end template code will display the msg\r\nusing HTML formatting, no coding required."
},
{
"id": "510ba5174729ba58",
"type": "uibuilder",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "",
"topic": "",
"url": "works-in-uib",
"fwdInMessages": false,
"allowScripts": false,
"allowStyles": false,
"copyIndex": true,
"templateFolder": "svelte-basic",
"extTemplate": "",
"showfolder": false,
"reload": true,
"sourceFolder": "dist",
"deployedVersion": "6.1.1",
"showMsgUib": true,
"x": 730,
"y": 300,
"wires": [
[
"7d15b868a5a04fe9"
],
[
"6d43a3fa23e4b6a1"
]
],
"info": "This example uses the default blank template.\r\n\r\nIt does not use any front-end framework, just\r\npure HTML, CSS and JavaScript."
},
{
"id": "7d15b868a5a04fe9",
"type": "debug",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "uibuilder standard output",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "counter",
"x": 865,
"y": 260,
"wires": [],
"l": false,
"info": "This shows the data coming out of the\r\nuibuilder node's Port #1 (top) which is\r\nthe standard output.\r\n\r\nHere you will see any standard msg sent from\r\nyour front-end code."
},
{
"id": "6d43a3fa23e4b6a1",
"type": "debug",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "uibuilder control output",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "counter",
"x": 865,
"y": 320,
"wires": [],
"l": false,
"info": "This shows the data coming out of the\r\nuibuilder node's Port #2 (bottom) which is\r\nthe control output.\r\n\r\nHere you will see any control msg either sent\r\nby the node itself or from the front-end library.\r\n\r\nFor example the \"client disconnect\" and\r\n\"client connect\" messages. Or the \"visibility\"\r\nmessages from the client.\r\n\r\nLoop the \"client connect\", \"cache replay\" and\r\n\"cache clear\" messages back to a `uib-cache`\r\nnode before the input to uibuilder in order\r\nto control the output of the cache."
},
{
"id": "389c413ade10fbab",
"type": "inject",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "Reload",
"props": [
{
"p": "_ui",
"v": "{\"method\":\"reload\"}",
"vt": "json"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "reload",
"x": 370,
"y": 360,
"wires": [
[
"c8747853bc7976e2"
]
],
"info": "Sends a pre-formatted msg to the front-end that\r\ncauses the page to reload itself."
},
{
"id": "9083ec150141c389",
"type": "inject",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "\"This is the payload from the inject node! Random number: \" & $formatInteger($random()*100, \"0\")",
"payloadType": "jsonata",
"x": 335,
"y": 240,
"wires": [
[
"2fa24135bc2c67f5"
]
],
"l": false
},
{
"id": "2fa24135bc2c67f5",
"type": "function",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "Notification",
"func": "msg = {\n \"_uib\": {\n // This can actually be anything, if it doesn't exist, \n // the toast will appear in the default location\n \"componentRef\": \"globalNotification\",\n // Note that most if not all of these are optional\n \"options\": {\n // These can contain HTML - note the inclusion of the payload from the upstram msg\n \"title\": \"This is the <i>title</i>\",\n \"content\": `This is content <span style=\\\"color:red;\\\">in addition to</span> the payload<p>${msg.payload}</p>`,\n \n // Use 1 of the following 2 - click msg if no auto hide:\n // \"autoHideDelay\": 2500,\n \"noAutoHide\": true,\n\n // If false or not included, msgs stack above each other.\n \"appendToast\": true,\n\n // See \"Recommended surfaces\" in uib-brand.css. Normally\n // 'primary', 'secondary', 'success', 'info', 'warn', 'warning', 'failure', 'error', 'danger'\n \"variant\": \"info\",\n }\n }\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 240,
"wires": [
[
"c8747853bc7976e2"
]
],
"info": "Overlays a message on top of your UI.\r\n\r\nThe message removes itself after a couple of seconds.\r\n\r\nYou can change the options property to change the look\r\nof the displayed message."
},
{
"id": "b6f1c7d8e58d2770",
"type": "inject",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 335,
"y": 280,
"wires": [
[
"bb67fc0d7d19c966"
]
],
"l": false
},
{
"id": "bb67fc0d7d19c966",
"type": "function",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "New Card",
"func": "let cardCounter = context.get('cardCounter') ?? 0\n\nmsg = {\n \"_ui\": [\n {\n \"method\": \"remove\",\n \"components\": [\n \"#mycard\"\n ]\n },\n {\n \"method\": \"add\",\n \"parent\": \"#more\",\n \"components\": [\n {\n \"type\": \"div\",\n \"attributes\": {\n \"id\": \"mycard\",\n \"title\": \"This is my Card\",\n \"style\": \"max-width: 20rem;border:solid silver 1px;margin-bottom:1rem;\",\n },\n \"components\": [\n {\n \"type\": \"h2\",\n \"slot\": \"A New Card\",\n \"attributes\": {\n \"class\": \"complementary\",\n \"style\": \"text-align:center;margin-top:0;\"\n }\n },\n {\n \"type\": \"p\",\n \"slot\": \"Some text in a paragraph.\"\n },\n {\n \"type\": \"p\",\n \"slot\": \"Another paragraph. Count: \" + ++cardCounter\n }\n ]\n }\n ],\n }\n ]\n}\ncontext.set('cardCounter', cardCounter)\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 440,
"y": 280,
"wires": [
[
"c8747853bc7976e2"
]
],
"info": "Inserts a pure HTML \"card\" into a div called `#more`.\r\nIf that div does not exist, will add to the bottom of the HTML.\r\n\r\nFirstly attempts to remove the div so that you only ever have 1.\r\n\r\nAn example of using uibuilder's dynamic UI configuration-driven\r\nbuilding capabilities without the need for any fancy nodes or\r\nframeworks. Pure HTML. But you can still utilise the extra\r\nfeatures of your favourite framework too if you like!"
},
{
"id": "fadf802d93c76823",
"type": "comment",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "Simple Svelte Example. Chk Description in each node. Read me too",
"info": "This example will work once you have set and\ndeployed the URL. However, if you want to make\nany changes to the front-end code, Svelte \nrequires you to _rebuild_ the destination\noutput.\n\n## Preparing\n1. Go to the server command line and navigate\nto the folder containing this example instance.\n2. In the instance root folder, run\n`npm install`. This will install all of the\nrequired development tools.\n3. Now run `npm run dev`. This starts a live\ndevelopment server and it gives you a URL.\n**IGNORE** the URL it gives you, because you\nare using Node-RED and uibuilder, you don't\nneed it 😎. Instead, you will now find that\nyour web page will automatically reload \nwhenever you save a change.\n\n## Making changes\nMost of the changes you will make will be to\nfiles in the `src` folder. However, if you\nneed to change the global CSS or the outer\nHTML template, these are in the root of the \n`dist` folder. Do not change anything in \n`dist/build` as this is overwritten by the \nSvelte build process.\n\n## Deploying\nOnce you have finished making changes, kill\nthe dev server then run `npm run build`.\n\nThat creates the final version of the code in\nthe dist folder.\n\nRemember: You are running your live pages from\nthe `dist` folder not the `src` folder.",
"x": 540,
"y": 180,
"wires": []
},
{
"id": "04d7537d634caec2",
"type": "inject",
"z": "afe95d068c771742",
"g": "60aeacf943e5cc5d",
"name": "Plain DL List (Array)",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "auto-create-dl-list",
"payload": "[[\"Entry One\",\"Description One\"],[\"Entry Two\",\"Description Two a\",\"Description Two b\",\"Description Two c\"],[\"Entry Three\",\"Description Three\"],[\"Entry Four\",\"Description Four\"]]",
"payloadType": "json",
"x": 450,
"y": 480,
"wires": [
[
"3c10deba5a5b82a6"
]
]
},
{
"id": "3c10deba5a5b82a6",
"type": "uib-element",
"z": "afe95d068c771742",
"g": "60aeacf943e5cc5d",
"name": "",
"topic": "eltest-dl",
"elementtype": "dl",
"parent": "#more",
"parentSource": "#more",
"parentSourceType": "str",
"elementid": "eltest-dl",
"elementIdSourceType": "str",
"heading": "My DL Heading (h3)",
"headingSourceType": "str",
"headingLevel": "h3",
"position": "last",
"positionSourceType": "str",
"confData": {},
"x": 690,
"y": 480,
"wires": [
[
"c8747853bc7976e2"
]
]
},
{
"id": "ff162c4ee10a16ec",
"type": "inject",
"z": "afe95d068c771742",
"g": "60aeacf943e5cc5d",
"name": "Remove",
"props": [
{
"p": "mode",
"v": "remove",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 480,
"y": 520,
"wires": [
[
"3c10deba5a5b82a6"
]
]
},
{
"id": "99ce70c0181b2927",
"type": "inject",
"z": "afe95d068c771742",
"g": "e425a6e20ba8c7ed",
"name": "Toggle Visible Msgs",
"props": [
{
"p": "_uib",
"v": "{\"command\":\"showMsg\",\"prop\":\"body\"}",
"vt": "json"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 410,
"y": 400,
"wires": [
[
"c8747853bc7976e2"
]
],
"info": "Change the \"prop\" value to a CSS Selector.\r\n\r\nThe display will appear as the last child of\r\nthat selected element.\r\n\r\ne.g. `body` or `#more`."
},
{
"id": "de5fb32c0c074133",
"type": "uibuilder",
"z": "afe95d068c771742",
"name": "",
"topic": "",
"url": "does-not-work",
"fwdInMessages": false,
"allowScripts": false,
"allowStyles": false,
"copyIndex": true,
"templateFolder": "svelte-basic",
"extTemplate": "",
"showfolder": false,
"reload": true,
"sourceFolder": "dist",
"deployedVersion": "6.1.1",
"showMsgUib": true,
"credentials": {},
"x": 370,
"y": 920,
"wires": [
[
"9e8f346d087d5d82"
],
[
"54f6b14b46a2408e"
]
],
"info": "This example uses the default blank template.\r\n\r\nIt does not use any front-end framework, just\r\npure HTML, CSS and JavaScript."
},
{
"id": "b81da2778231aebd",
"type": "comment",
"z": "afe95d068c771742",
"name": "The same example, with <style> and without <style>",
"info": "According to the svelte documentation, the <style> </style> is supposed to create a CSS componment inside something.\n\"This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. svelte-123xyz).\"-Svelte doc\nthis works fine for me in svelte without UIbuilder.\nThe snag I was hitting is that <style></style> does not seem to be affecting anything.\nTo make things look right I manually ahve to do what styles says it is doing, by adding it to the global CSS file.\nThe first example here works for me in svelte without ui builder, and when i say works, i mean it looks like the example is supposed to.\nUibuilder does not seem to agree to use the style, and is using only global? as when i move the same style parameters into global\nit just works (tm).\nThe second example i have moved the style of Thing.svelte into global.css and everything works.\nThe first example does not do it, and thus comes out as if no CSS has been added.\n\nUi builder is amazin tho, i think this just needs a note in the wiki about it, and a possible fix in future. :)",
"x": 490,
"y": 740,
"wires": []
},
{
"id": "ce44cfd442aad60e",
"type": "uibuilder",
"z": "afe95d068c771742",
"name": "",
"topic": "",
"url": "Styles-moved-to-css",
"fwdInMessages": false,
"allowScripts": false,
"allowStyles": false,
"copyIndex": true,
"templateFolder": "svelte-basic",
"extTemplate": "",
"showfolder": false,
"reload": true,
"sourceFolder": "dist",
"deployedVersion": "6.1.1",
"showMsgUib": true,
"x": 380,
"y": 1160,
"wires": [
[
"5510f88863d7f490"
],
[
"5e0d1058487d3776"
]
],
"info": "This example uses the default blank template.\r\n\r\nIt does not use any front-end framework, just\r\npure HTML, CSS and JavaScript."
},
{
"id": "5510f88863d7f490",
"type": "debug",
"z": "afe95d068c771742",
"name": "uibuilder standard output",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "counter",
"x": 545,
"y": 1120,
"wires": [],
"l": false,
"info": "This shows the data coming out of the\r\nuibuilder node's Port #1 (top) which is\r\nthe standard output.\r\n\r\nHere you will see any standard msg sent from\r\nyour front-end code."
},
{
"id": "5e0d1058487d3776",
"type": "debug",
"z": "afe95d068c771742",
"name": "uibuilder control output",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "counter",
"x": 545,
"y": 1180,
"wires": [],
"l": false,
"info": "This shows the data coming out of the\r\nuibuilder node's Port #2 (bottom) which is\r\nthe control output.\r\n\r\nHere you will see any control msg either sent\r\nby the node itself or from the front-end library.\r\n\r\nFor example the \"client disconnect\" and\r\n\"client connect\" messages. Or the \"visibility\"\r\nmessages from the client.\r\n\r\nLoop the \"client connect\", \"cache replay\" and\r\n\"cache clear\" messages back to a `uib-cache`\r\nnode before the input to uibuilder in order\r\nto control the output of the cache."
},
{
"id": "9e8f346d087d5d82",
"type": "debug",
"z": "afe95d068c771742",
"name": "uibuilder standard output",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "counter",
"x": 535,
"y": 900,
"wires": [],
"l": false,
"info": "This shows the data coming out of the\r\nuibuilder node's Port #1 (top) which is\r\nthe standard output.\r\n\r\nHere you will see any standard msg sent from\r\nyour front-end code."
},
{
"id": "54f6b14b46a2408e",
"type": "debug",
"z": "afe95d068c771742",
"name": "uibuilder control output",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "counter",
"x": 535,
"y": 940,
"wires": [],
"l": false,
"info": "This shows the data coming out of the\r\nuibuilder node's Port #2 (bottom) which is\r\nthe control output.\r\n\r\nHere you will see any control msg either sent\r\nby the node itself or from the front-end library.\r\n\r\nFor example the \"client disconnect\" and\r\n\"client connect\" messages. Or the \"visibility\"\r\nmessages from the client.\r\n\r\nLoop the \"client connect\", \"cache replay\" and\r\n\"cache clear\" messages back to a `uib-cache`\r\nnode before the input to uibuilder in order\r\nto control the output of the cache."
},
{
"id": "faf1d4f7da85ff36",
"type": "comment",
"z": "afe95d068c771742",
"name": "global.css",
"info": "// nothing in here",
"x": 240,
"y": 820,
"wires": []
},
{
"id": "a26fe59c74d448c6",
"type": "comment",
"z": "afe95d068c771742",
"name": "global.css",
"info": "span {\n\t\tdisplay: inline-block;\n\t\tpadding: 0.2em 0.5em;\n\t\tmargin: 0 0.2em 0.2em 0;\n\t\twidth: 4em;\n\t\ttext-align: center;\n\t\tborder-radius: 0.2em;\n\t\tcolor: white;\n\t}",
"x": 260,
"y": 1040,
"wires": []
},
{
"id": "439a52c74e26ff09",
"type": "comment",
"z": "afe95d068c771742",
"name": "App.svelte",
"info": "<script>\n\timport Thing from './Thing.svelte';\n\n\tlet things = [\n\t\t{ id: 1, color: 'darkblue' },\n\t\t{ id: 2, color: 'indigo' },\n\t\t{ id: 3, color: 'deeppink' },\n\t\t{ id: 4, color: 'salmon' },\n\t\t{ id: 5, color: 'gold' }\n\t];\n\n\tfunction handleClick() {\n\t\tthings = things.slice(1);\n\t}\n</script>\n\n<button on:click={handleClick}>\n\tRemove first thing\n</button>\n\n<div style=\"display: grid; grid-template-columns: 1fr 1fr; grid-gap: 1em\">\n\t<div>\n\t\t<h2>Keyed</h2>\n\t\t{#each things as thing (thing.id)}\n\t\t\t<Thing current={thing.color}/>\n\t\t{/each}\n\t</div>\n\n\t<div>\n\t\t<h2>Unkeyed</h2>\n\t\t{#each things as thing}\n\t\t\t<Thing current={thing.color}/>\n\t\t{/each}\n\t</div>\n</div>\n",
"x": 380,
"y": 820,
"wires": []
},
{
"id": "f07acf2014761645",
"type": "comment",
"z": "afe95d068c771742",
"name": "App.svelte (not changed)",
"info": "<script>\n\timport Thing from './Thing.svelte';\n\n\tlet things = [\n\t\t{ id: 1, color: 'darkblue' },\n\t\t{ id: 2, color: 'indigo' },\n\t\t{ id: 3, color: 'deeppink' },\n\t\t{ id: 4, color: 'salmon' },\n\t\t{ id: 5, color: 'gold' }\n\t];\n\n\tfunction handleClick() {\n\t\tthings = things.slice(1);\n\t}\n</script>\n\n<button on:click={handleClick}>\n\tRemove first thing\n</button>\n\n<div style=\"display: grid; grid-template-columns: 1fr 1fr; grid-gap: 1em\">\n\t<div>\n\t\t<h2>Keyed</h2>\n\t\t{#each things as thing (thing.id)}\n\t\t\t<Thing current={thing.color}/>\n\t\t{/each}\n\t</div>\n\n\t<div>\n\t\t<h2>Unkeyed</h2>\n\t\t{#each things as thing}\n\t\t\t<Thing current={thing.color}/>\n\t\t{/each}\n\t</div>\n</div>\n",
"x": 450,
"y": 1040,
"wires": []
},
{
"id": "7b90cb0ac8803250",
"type": "comment",
"z": "afe95d068c771742",
"name": "Thing.svelte",
"info": "\n<script>\n\t// `current` is updated whenever the prop value changes...\n\texport let current;\n\n\t// ...but `initial` is fixed upon initialisation\n\tconst initial = current;\n</script>\n\n<p>\n\t<span style=\"background-color: {initial}\">initial</span>\n\t<span style=\"background-color: {current}\">current</span>\n</p>\n\n<style>\n\tspan {\n\t\tdisplay: inline-block;\n\t\tpadding: 0.2em 0.5em;\n\t\tmargin: 0 0.2em 0.2em 0;\n\t\twidth: 4em;\n\t\ttext-align: center;\n\t\tborder-radius: 0.2em;\n\t\tcolor: white;\n\t}\n</style>",
"x": 670,
"y": 820,
"wires": []
},
{
"id": "949d12231c2537c9",
"type": "comment",
"z": "afe95d068c771742",
"name": "Thing.svelte",
"info": "<script>\n\t// `current` is updated whenever the prop value changes...\n\texport let current;\n\n\t// ...but `initial` is fixed upon initialisation\n\tconst initial = current;\n</script>\n\n<p>\n\t<span style=\"background-color: {initial}\">initial</span>\n\t<span style=\"background-color: {current}\">current</span>\n</p>\n\n<style>\n\tspan {\n\t\tdisplay: inline-block;\n\t\tpadding: 0.2em 0.5em;\n\t\tmargin: 0 0.2em 0.2em 0;\n\t\twidth: 4em;\n\t\ttext-align: center;\n\t\tborder-radius: 0.2em;\n\t\tcolor: white;\n\t}\n</style>",
"x": 670,
"y": 1040,
"wires": []
}
]