Custom mutators for custom if/ else blocks

137 views
Skip to first unread message

Jing An Tew

unread,
Jun 1, 2025, 7:53:57 PMJun 1
to Blockly
Hi, is there a tutorial or more beginner friendly guide of how to create/ define mutators for custom blocks? Do we have to use XML to create the mutation UI?
Screenshot 2025-05-14 230050.png

Jing An Tew

unread,
Jun 1, 2025, 7:56:00 PMJun 1
to Blockly
And also, will there ever be tutorials on how to create the default blocks contained within Blockly/blocks? It would provide a lot of insight on how to redevelop custom blocks

Ronald Bourret (xWF)

unread,
Jun 2, 2025, 1:53:57 PMJun 2
to blo...@googlegroups.com
Hi,

We do not have plans for more tutorials at the moment. However, we will keep your ideas in mind.

Mutators
For mutators, the important things to remember are:
  • A mutator is a mixin that provides either saveExtraState and loadExtraState (for saving to JSON) or it provides mutationToDom and domToMutation (for saving to XML). You  can also provide both pairs of functions.
  • If you want a UI so the user can modify the shape of the block, you can use the default UI or create your own UI, such as the +/- mutator blocks.
  • If you use the default UI, you need to understand the following:
    • The UI that pops up is a separate workspace. This workspace has its own toolbox and its own set of blocks; these blocks are used to configure the real block (see picture below).
    • The decompose function (which the mutator mixin implements) takes the real block and populates/configures the mutator workspace, which is passed to decompose. See the documentation for an example of the decompose function code for the lists_create_with block.
    • The compose function (which the mutator mixin also implements) takes the block in the mutator UI and updates the real block.
    • The saveConnections function (optional, also implemented by the mutator mixin) is used to save connections to child blocks. compose uses this information when rebuilding the real block.
Let us know if you have questions about this.
image.png
Defining custom blocks
If you are new to Blockly, I suggest you read What's a block definition? and Anatomy of a block, then play with the Block Factory and look at the JSON that is generated. If you want to play with your own code and haven't set up a Blockly environment yet, you can start with this JSFiddle.

Again, let us know if you have specific questions.

Ronald Bourret
Technical Writer (Provided by Synergis)


--
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 visit https://groups.google.com/d/msgid/blockly/d6238c92-2104-4b7f-be41-f68d049e8395n%40googlegroups.com.

Jing An Tew

unread,
Jun 6, 2025, 8:20:56 AMJun 6
to Blockly
Hi, is there sample code regarding how to setup a simple block like this? For e.g. the IfElseIfElse block. Sorry, although I have some prior experience building custom blocks, I'm kind of confused where exactly to start building a IfElseIfElse block.

Thanks.

Max Stephen Russell

unread,
Jun 6, 2025, 8:53:43 AMJun 6
to Blockly

Jing An Tew

unread,
Jun 6, 2025, 11:17:06 AMJun 6
to Blockly
Hi, I have looked at the link, it's just that I'm a bit more lost in that file due to all the extra imports and I'm just not sure where to start

Max Stephen Russell

unread,
Jun 6, 2025, 12:36:46 PMJun 6
to Blockly
Jing An Tew,

I can say one more thing that might help you in your situation. If you tell Grok 3 your problem, very specifically, such as what you have said in this conversation -- "I'm kind of confused where exactly to start building a IfElseIfElse block" -- and include the word "Blockly", you might be very happy with the response. Grok has come a long way in understanding Blockly. After doing a lot of hard work and study and also getting tremendous help in this group, I now use Grok as a super-helpful collaborator when doing Blockly stuff.

-Steve

Mark Friedman

unread,
Jun 6, 2025, 1:28:28 PMJun 6
to blo...@googlegroups.com
Jing An Tew,

  Mutators are one of the more complex areas of Blockly, so it's not too surprising that you have some difficulties understanding it.  We've posted a bunch of explanations and links for you to take a look at.  However, even with all that it can be difficult to understand without a decent amount of experience with general Blockly development and general Blockly concepts.  So one suggestion I would have would be to do some app development using Blockly that doesn't require creating a custom block that needs a mutator.  

  Related to the above, try to read as much of the developer guides (here) as you can (and do any codelabs that you encounter in the guides), to give yourself a good well-rounded knowledge of Blockly concepts. And, of course, feel free to post any questions that you have about what you read or what you've tried.  If your question is code-related, please include that code (or a link to it) in your post.

  Hope this helps.

-Mark


Ronald Bourret (xWF)

unread,
Jun 6, 2025, 2:37:09 PMJun 6
to blo...@googlegroups.com
Hi,

I agree with Mark that mutators are one of the more complex parts of Blockly.

Don't worry too much about the import statements. These just import the pieces of Blockly used by the logic blocks.

Here's some suggestions on how to break the controls_if mutator into understandable pieces:

1) Use the playground to play with a mutator and understand the difference between the block in the main workspace (controls_if) and the blocks in the mutator workspace (controls_if_ifcontrols_if_elseifcontrols_if_else).

2) Read the code to learn how decompose constructs the mutator workspace from the controls_if block in the main workspace. (decompose is called by the mutator icon.)

3) Read the code to learn how compose updates the controls_if block in the main workspace every time you make a change in the mutator workspace. (compose is also called by the mutator icon.) This is also a good time to look at how compose uses updateShape_.

4) In the playground, connect some boolean blocks and statement blocks to your controls_if block. Now change the shape of the controls_if block using the mutator block and see what happens to these blocks. Next, read the code in saveConnections and reconnectChildBlocks_ to see how this works. This code takes some time to understand.

5) Look at the call to registerMutator -- this registers the mutator with Blockly so the mutator icon knows what functions to call. The last argument of this call is an array that tells the mutator icon which blocks to put in the mutator workspace's toolbox.

6) Look at the code in saveExtraState and loadExtraState, which saves state to/loads state from JSON. You can ignore mutationToDom, domToMutation, and rebuildShape_ unless you want to save to/load from XML.

Good luck!

Ronald Bourret
Technical Writer (Provided by Synergis)

Jing An Tew

unread,
Jun 7, 2025, 12:52:28 AMJun 7
to Blockly
Hi, thanks for all the helpful insights. I just wish to ask, how would one go about attaching a mutator to an existing block that was initialized using Javascript. For JSON definitions I understand a mutator is first registered under the `Blockly.Extensions.registerMutator` method, then attached to the block definition using the `mutator` property in the JSON definition. What would be the equivalent of initializing mutators using Javascript for the blocks? 

Attached below is some sample code I currently have in my workspace. Currently I have not implemented all the remaining functions so they can be ignored for now.
how.png

fu6...@gmail.com

unread,
Jun 9, 2025, 12:34:43 AMJun 9
to Blockly
Hi  jinga...,

I once wrote a "Switch case" example that I can provide for your reference.

Best wishes

France

jinga...@gmail.com 在 2025年6月7日 星期六中午12:52:28 [UTC+8] 的信中寫道:

Ronald Bourret (xWF)

unread,
Jun 9, 2025, 1:10:11 PMJun 9
to blo...@googlegroups.com
To define a mutator in JavaScript, just add the mutator functions directly to your block definition and call setMutator in your init function:

Blockly.Blocks["myblock"] = {
  init: function () {
    ...
    this.setMutator(new Blockly.icons.MutatorIcon(['my_mutator_block1', 'my_mutator_block2'], this));
  },
  saveExtraState: function () {...},
  loadExtraState: function (state) {...},
  decompose: function (workspace) {...},
  compose: function (containerBlock) {...},
  saveConnections: function (containerBlock) {...},
}


You don't need to register the mutator because that is just a way for the JSON-based code to add the functions in a mutator mixin to your block definition.

Ronald Bourret
Technical Writer (Provided by Synergis)

Reply all
Reply to author
Forward
0 new messages