Uibuilder + svelte issues

Hi,
So I was trying to learn how to use uibuilder with svelte, but came across an interesting issue and was wondering if anyone knows why this happens.
Simply copying the examples from the svelte homepage into node-red ui builder creates different pages for me.
I feel like there is something obvious I am missing?


This even fails on the basic just use comic sans and everything?

Check the css file

1 Like

? I don't see anything failing ?

As buckskin say's, you need to check your CSS. uibuilder auto-loads a CSS file for you if you don't provide one which applies some (hopefully) sane standards.

As always, check in the browser dev tools to see exactly what the browser is doing.


BTW, assuming that you are using uibuilder v6.1, there is a svelte example in the Templates example.

Load that example in and you will see that it contains examples for each built-in template including Svelte.

Hopefully is enough to get you going.

After a load of testing i found the problem that was actually bothering me so.
All the tutorials i have checked out use the style thingy to make everything look nice. However that never worked for me.
Strangely when I copy that into the CSS file, magic happens and everything comes to life as i expected it to do.
This does not happen if I run Svelte without uibuilder.
Luckily for me I am fine with using global for everything as i plan to be using SVGs for the main page. However this is a funny issue.
Tried on 2 computers and the same result.
Might be worth looking more into : )
The template test works as it does not use the style thingy

I think that is more about getting your head around the way that Svelte handles such things. I've not really had any issues either way.

Sorry, not sure what you mean here. Could you please share some code? I'll take a look.

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": []
    }
]

How it looks from my end,

Yep, there seems to be a problem with rollup - it isn't including the svelte file styles except for App.svelte.

Now we need to work out why that is happening.

OK, I think I've spotted the problem.

A quick workaround is to add emitCss: false, to rollup.config.js:

        svelte({
            compilerOptions: {
                // enable run-time checks when not in production
                dev: !production
            },
            emitCss: false,
        }),

I need to get some lunch. I'll look for a more complete solution afterwards.


Svelte template fails to compile additional svelte file styles · Issue #204 · TotallyInformation/node-red-contrib-uibuilder (github.com)

Right. Got it. It wasn't a uibuilder bug at all!

It was a change in the rollup-plugin-svelte rollup plugin! :frowning:

If you check your dist folder, you will find that there is a dist/build/dist/build folder - and it turns out that the output specifications for the svelte plugin changed from requiring the full path to being relative to plugin's output folder :persevere:

So the actual solution is to change the line

css({ output: `${uibDist}/build/bundle.css` }),

to

css({ output: 'bundle.css' }),

I couldn't work out why this had stopped working when I was certain that I'd tested additional svelte files with styles.

Very annoying. Will be permanently fixed in v6.2 release.

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