Does anyone know of how to script compose at run t...
# multiplatform
a
Does anyone know of how to script compose at run time? I would like to use this for a Visual Block editor, example shown below. Note that I have this working at present using vanilla DHtml browser with dragulas.js. I want the users to be able to drag and drop blocks, reorder them, and also change the menu/textfield, etc. The components would also be used to generate (javascript) code to execute (this would likely run in a new window). Here is sample block code - which I would like to use Compose for instead - I am certain this can be massively reduced
Copy code
<div data-quando-block-type="media-text" class="quando-block"
    data-quando-javascript="quando.text($(eq$,${txtval}$,input$,'${text}'$,${txtval})$,${append},${newline})">
    <div class="quando-left quando-media"></div>
    <div class="quando-right">
        <div class="quando-row quando-media">
            <span class="iconify">abc</span>
            <select data-quando-name="append" class='quando-toggle'>
                <option value="false">Show</option>
                <option value="true">Add</option>
            </select>
            Text
            <span data-quando-toggle='txtval=input'>
                "<input data-quando-name="text" type="text" value=""
                    data-quando-encode='normal' />"
            </span>
            <select data-quando-name='newline' class='quando-toggle'>
                <option value='false'> </option>
                <option value='true'>⤶</option>
            </select>
<!-- + options removed -->
        </div>
    </div>
</div>
At present I just paste the html into the relevant div - but this won't work for compose. Hot reload 'could' do this but is an IDE feature - so not suitable for separate builds. Note that there are 200+ blocks at present, so a switch statement would be a maintenance nightmare...I could put them all in a list and iterate through - but that seems smelly... Thank you in advance - Andy
👍 1
m
Using a list (or more specifically a hierarchy) of well thought structures seems to be the right thing for me. It represents what the script is, and can help with other features like rendering the blocks and serializing it to be saved. In the case of the suggested html way, trying to know what the user has added previously can be a nightmare. You may think of tracking them in a separate location, but this violates "single source of truth" allowing inconsistencies between the blocks and the rendered content.
c
Nothing about this structure requires Composables to be modified at runtime. You'll have a list of nodes that represents your current app state, and your Compose UI will reflect that state. Your drag-and-drop UX should show some comparison between the existing app state and potential new states. The 'hard' part of drag-and-drop isn't editing the app state in realtime, it's showing a preview of a potential app state in realtime. The primary UI for this would look something like this:
LazyList() { items(appState.nodes) { node -> node.render() } }
Nodes that wrap other nodes (like your 'every' example) should be represented as a single node with a property that contains a list of nodes they contain. In other words, the node list will be multi-dimensional, containing nested lists of nodes, not a flattened list. The need to generate/inject javascript into a new Window is also not really a problem: just use document.write() as you would in normal javascript code. And don't worry about rewriting the javascript during drag events. Wait til the state change is finalized before bothering with that, and things should go much smoother. Each of your nodes will need a rendering function and a javascript export function. I think that's about everything, but let me know if I've missed one of your problems!
a
Thank you @Mohamed Darwish - I was coming to the conclusion that that was the Compose way of doing things - but I wanted to check in case there was a closer way to my current approach. Note that I currently do have a single source of truth - I use the DOM itself to store the state - yes that does smell...
Thank you @Coty Saxman you also added some more useful detail - the lazy list was already a target for me - nice to see it confirmed. If you know of any examples doing something similar, it would be great if you could post a link - the examples I have found so far focus on very simple drag and drop for just reordering and don't show containers.