简体   繁体   中英

How can I dynamically generate content of a Blockly dropdown menu?

I am writing an application using python and flask. In the webinterface, the user is able to make small customized programs using blockly.

Some of the already existing blocks have a dropdown menu.

All that works fine. But now I want to have a block with a dropdown menu where the options are certain files on a usb stick the python backend found by walking through the usb stick directory.

I would like to fill the dropdown menu with these files now. I cannot, however, know them in advance and that is why they have to be dynamically generated - but by python, not by javascript or that like.

I already found this here: https://developers.google.com/blockly/guides/create-custom-blocks/dropdown-menus (at "Dynamic menu" at the end), but that does not help in my case, since I want the information to come from the python backend and not from javascript.

Does anyone know a way to do this?

Thank you a lot in advance!

This is a pretty old question, so I'm not sure if the OP still needs an answer, but I'm answering on the assumption that this is a situation where the OP is using an asynchronous JavaScript call to the backend and can't just return the results because of that.

We have a not dissimilar situation in our application (albeit using a nodejs backend) where we're populating dropdowns based on options retrieved from Google Cloud Datastore. We have a React App, so our solution was to have a Flux store attached to the window which our asynchronous call populates upon completing, and then have the dropdown generation code access that store. Obviously, a full Flux store may not be appropriate for all situations, but my general advice here would be to pass in an option generator function and have it read from a store or other variable on the window, and then have your call to the backend run on page load (or when otherwise appropriate) and populate the store on the window. If your app inits before the call is done, you can have it set up to show that it's loading options based on a flag on the store.

As a very simplified case, you might have:

// on page load
window.store = {done: false};
myBackendCall()
.then(function(results){
    window.store = {
        results: results,
        done: true
    };
})
.catch(function(error){
    console.error(error);
    window.store = {results: [], done: true};
});

Then in your selector, you might go with something like:

function generateOptions(){
    if(!window.store.done) {
        return [['Loading...', 'loading']];
    } else {
        return [['Select a file', '']].concat(window.store.results);
    }
}
this.appendDummyInput()
    .appendField(new Blockly.FieldDropdown(generateOptions), fieldName);

Obviously, this is a gross simplification, but I think it's enough to show the technique. We actually made our own custom Blockly fields for this for other reasons, but this should still work with a vanilla Blockly dropdown. Swap out Promise chaining for callbacks if that's how your setup is. You could also make the call inside the block and set a variable on the block itself ( this.store or whatever), but that would result in multiple calls being made for multiple instances of the block, so that may not be appropriate for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM