Creating a block like Function Block (procedure) that creates a new block in toolbox

194 views
Skip to first unread message

Frank Cappelle

unread,
Jan 17, 2023, 7:13:01 PM1/17/23
to Blockly
Hello and thank you!

I need to create a block that emulates the "Function" block where a new block is created in the toolbox dynamically.

I have been able to create a block in the toolbox dynamically using a javascript array.
However, I was hoping that when I drag a block onto the workspace and change its name, that a new block would be created with that name.

Any direction would be very helpful!

Thanks,
Frank

Ahana Ghosh

unread,
Jan 19, 2023, 6:58:05 AM1/19/23
to blo...@googlegroups.com
Hi All!

I also had a similar question 😅 Does anyone have any pointers on how to do this? Currently, the new block gets created only when categories are present.

Regards,
Ahana

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/40973836-182d-485e-a620-50aef8f0b208n%40googlegroups.com.

Maribeth Bottorff

unread,
Jan 19, 2023, 5:17:12 PM1/19/23
to Blockly
Hello,

For where to start with this, I would check out the built-in Procedures category code as well as the documentation for dynamic categories.

The way the procedures category works is it is a dynamic category, which means whenever it is clicked from the toolbox, a function is called that returns the contents of the category. Since that function is called every time the category is opened, the contents of the category can be calculated on the fly. For procedures, this means we inspect the blocks on the workspace to find out what procedure caller blocks we need to add. For your custom blocks, it is up to you how you decide which blocks to add (looking at other blocks on the workspace, consulting your own source of data, etc).

For Ahana, it sounds like you are asking how to update a "simple" (flyout-only) toolbox that doesn't have categories. Is that correct? If not, please write back with more details about your question. If it is, one approach is to listen for block change/create events and use the API to update the toolbox  when a relevant change occurs. So you'd register a change listener, listen for create events, and if the event is relevant then update the toolbox contents however you like.

Would either of those approaches work for you? If not or if you have further questions, adding more detail about your use case and any code you've currently attempted would be really useful.

Maribeth

Ahana Ghosh

unread,
Jan 20, 2023, 6:26:17 AM1/20/23
to blo...@googlegroups.com
Thanks so much Maribeth! Yes, I was asking about the dynamic update of the flyout toolbox directly, for a functions block. We will try out your suggested method and get back to you.

Regards,
Ahana

fu6...@gmail.com

unread,
Jan 20, 2023, 6:34:38 AM1/20/23
to Blockly
Hi,  frank.c...
I tried to make it. Hope this helps.


toolbox.xml

<category id="catMyProcedure" name="%{BKY_MYPROCEDURE_TITLE}" colour="%{BKY_MYPROCEDURE_HUE}"  custom="MYPROCEDURE"></category>



javascript.js

Blockly.Msg["MYPROCEDURE_TITLE"] = "myProcedure";
Blockly.Msg["MYPROCEDURE_HUE"] = "120";

Blockly.myProcedure={};
Blockly.myProcedure_CATEGORY_NAME="MYPROCEDURE";
Blockly.myProcedure.NAME_TYPE=Blockly.myProcedure_CATEGORY_NAME;

Blockly.Blocks['test'] = {
  init: function() {
    this.appendDummyInput()
        .appendField("NAME")
        .appendField(new Blockly.FieldTextInput(""), "NAME");
    this.setColour(230);
  }
};

Blockly.JavaScript['test'] = function(block) {
  var text_name = block.getFieldValue('NAME');
  var code = '...;\n';
  return code;
};

Blockly.myProcedure.flyoutCategory=function(workspace){
    var categoryBlocks = [];
    categoryBlocks.push(Blockly.Xml.textToDom('<block xmlns="https://developers.google.com/blockly/xml" type="test"><field name="NAME"></field></block>'));
   
    var blocksNAME = [""];

    var blocks = workspace.getBlocksByType("test", true);
    for (var i=0;i<blocks.length;i++){
        var value = blocks[i].getFieldValue("NAME");
        if (value!=""&&blocksNAME.indexOf(value)==-1) {
            blocksNAME.push(value);
            categoryBlocks.push(Blockly.Xml.textToDom('<block xmlns="https://developers.google.com/blockly/xml" type="test"><field name="NAME">'+value+'</field></block>'));
        }
    }
    return categoryBlocks;
};

var checkMyProcedure = function(){
    if(Blockly.getMainWorkspace() == null){
        setTimeout(checkMyProcedure, 200);
    } else {
        Blockly.myProcedure&&Blockly.myProcedure.flyoutCategory&&(Blockly.getMainWorkspace().registerToolboxCategoryCallback(Blockly.myProcedure_CATEGORY_NAME, Blockly.myProcedure.flyoutCategory));
    }
};
checkMyProcedure();



Best wish.
fu6...

mari...@google.com 在 2023年1月20日 星期五清晨6:17:12 [UTC+8] 的信中寫道:
flyout.mp4

Frank Cappelle

unread,
Jan 20, 2023, 7:54:14 AM1/20/23
to Blockly
Mari, Thanks so much!

I need to study it.
Your demo works exactly like  I was looking for.
Thank you for your time and effort.
I'll post back about my success.
Frank

Frank Cappelle

unread,
Jan 20, 2023, 8:19:13 AM1/20/23
to Blockly
Mari,
I got it to work!
Man-o-man... unbelievable!
Now for me to digest it and truly understand what's going on.
The learning is slow but the rewards are great.

Best wishes,
Frank

Reply all
Reply to author
Forward
0 new messages