Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

What is ValueConnection_?

56 views
Skip to first unread message

Josue Miguel Miguel Vasquez

unread,
Jan 17, 2025, 11:24:03 AMJan 17
to Blockly
I'm testing mutators for my project, and i'm triying to implement the mutators example from the Guides to make a mutable block similar to the built-in block "create list with". But I don't know what is the attribute ValueConnection_ (Also, the code gives an error related with reading properties of null). Could anyone tell me what is that attribute or how to implement what i'm trying to get?

Ronald Bourret

unread,
Jan 17, 2025, 1:51:24 PMJan 17
to blo...@googlegroups.com
Before answering your question, I'll explain how the UI editor works. It's easiest to see this if you play along with the Blockly Playground.

When you click the blue editor gear in a mutable block, Blockly creates a separate workspace -- the editor workspace. The editor workspace has its own blocks. These represent the parts of the block in the main workspace that is being edited. In the case of the create_lists_with block, the editor workspace has a container block ("list") and 0 or more blocks representing items in the list ("item"). As you add or remove item blocks from the list block in the editor workspace, Blockly updates the shape of the block in the main workspace. (Try it!)

Now let's see what valueConnection_ is.

Create a list block with two items in it and connect two text value blocks to it. The first piece of text should be "abc" and the second "def". Open the mutation editor and add a new item block between the existing two items. Notice what happens to the block in the main workspace: an empty value input is added between the inputs with "abc" and "def".

valueConnection_ is a property of the item block in the editor workspace. It stores the connection (if any) of the corresponding value block in the main workspace. (Remember that an item in the editor workspace corresponds to a value input on the block in the main workspace.) This is done so that the correct value block is connected to the correct value input after you make changes with the editor. In this case, valueConnection_ for the first item block is the connection to the "abc" block; valueConnection_ for the second item block is null; and valueConnection_ for the third item block is the connection to the "def" block.

valueConnection_ is set in the saveConnections function, which is discussed after the discussions of compose and decompose.

As to the error and how to implement what you want, we'll need more information. Can you describe what block you're trying to create, what code you're using, and what causes the error?

Thanks,

Ronald Bourret
Technical Writer (Provided by Synergis)


On Fri, Jan 17, 2025 at 8:23 AM Josue Miguel Miguel Vasquez <josue...@gmail.com> wrote:
I'm testing mutators for my project, and i'm triying to implement the mutators example from the Guides to make a mutable block similar to the built-in block "create list with". But I don't know what is the attribute ValueConnection_ (Also, the code gives an error related with reading properties of null). Could anyone tell me what is that attribute or how to implement what i'm trying to get?

--
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/ec13e0ce-de1c-4c1a-b22e-080c2882e2b2n%40googlegroups.com.

Josue Miguel Miguel Vasquez

unread,
Jan 21, 2025, 7:36:24 PMJan 21
to Blockly
Hi, sorry for late response, the code is this:

Blockly.Extensions.registerMutator("mutator_function_call_parameters",
  {

    parameters_count: 0,

    saveExtraState: function(){
      return {"parameters_count": this.parameters_count}
    },

    loadExtraState: function(state){
      this.parameters_count = state["parameters_count"]
      this.updateShape()
    },

    decompose:function(workspace){
      const function_parameters= workspace.newBlock("c_function_parameters")
      function_parameters.initSvg()
      var connection = function_parameters.getInput('PARAMETERS').connection;
      for (var i = 0; i < this.itemCount_; i++) {
        var itemBlock = workspace.newBlock('c_function_parameter_call');
        itemBlock.initSvg();
        connection.connect(itemBlock.previousConnection);
        connection = itemBlock.nextConnection;
      }
      return function_parameters
    },

    // The container block is the top-block returned by decompose.
    compose: function(topBlock) {
      // First we get the first sub-block (which represents an input on our main block).
      var itemBlock = topBlock.getInputTargetBlock('PARAMETERS');

      // Then we collect up all of the connections of on our main block that are
      // referenced by our sub-blocks.
      // This relates to the saveConnections hook (explained below).
      var connections = [];
      while (itemBlock && !itemBlock.isInsertionMarker()) {  // Ignore insertion markers!
        connections.push(itemBlock.valueConnection_);
        itemBlock = itemBlock.nextConnection &&
            itemBlock.nextConnection.targetBlock();
      }


      // Then we disconnect any children where the sub-block associated with that
      // child has been deleted/removed from the stack.
      for (var i = 0; i < this.itemCount_; i++) {
        var connection = this.getInput('PARAMETER_' + i).connection.targetConnection;
        if (connection && connections.indexOf(connection) == -1) {
          connection.disconnect();
        }
      }

      // Then we update the shape of our block (removing or adding iputs as necessary).
      // `this` refers to the main block.
      this.itemCount_ = connections.length;
      this.updateShape();

      // And finally we reconnect any child blocks.
      for (var i = 0; i < this.itemCount_; i++) {
        connections[i].reconnect(this, 'PARAMETER_' + i);
      }

    },

    updateShape: function(){
     
    }
  },
  null,
  ["c_function_parameter_call"]
)

You can notice that is the same code from the Extensions & Mutators section on Blockly guides but with different variable names.
The code shows the next error:

Uncaught TypeError: Cannot read properties of undefined (reading 'reconnect')
    at BlockSvg$$module$build$src$core$block_svg.compose (function.js:253:1)
    at $.MutatorIcon$$module$build$src$core$icons$mutator_icon.recomposeSourceBlock (blockly_compressed.js:815:18)
    at eval (blockly_compressed.js:813:490)

The Line 253 is this:
        connections[i].reconnect(this, 'PARAMETER_' + i);

I looked into the Blockly Block class and I didn't find any attribute with the name ValueConnection_ and when I print the array "connections", it prints an array with an undefined datatype.

Mark Friedman

unread,
Jan 21, 2025, 7:49:09 PMJan 21
to blo...@googlegroups.com
Josue,

  It looks like maybe you missed the part of the "Extensions and Mutators" guide where it talks about the saveConnections() function (here) and gives an example.  That example is where valueConnection_ is defined.  Please read Ronald's reply again.  He described the working of the mutator UI in detail and you'll see that he did mention where and why valueConnection_ is defined.

-Mark


Ronald Bourret

unread,
Jan 22, 2025, 11:21:02 AMJan 22
to blo...@googlegroups.com
And in case it wasn't clear, the code in the documentation is not complete -- it's only meant to illustrate the compose, decompose, and saveConnections functions. You can find the definitions of the blocks used in the UI editor (including the interface that defines valueConnection_)  here and here. You might need other code as well -- I haven't looked. 

Ronald Bourret
Technical Writer (Provided by Synergis)

Josue Miguel

unread,
Jan 22, 2025, 8:46:02 PMJan 22
to Blockly
Thanks for the responses!  I got confused easily because it was difficult for me to understand how mutators works ; also I only wanted to test mutators quickly to see if it was worth to implement in my project prototype. I see that I could simplify the code if I implement a custom plus and minus button, instead of using the subblocks, but because image fields are not serializable, I think it won't be possible to save the block with the workspace save function. So probably, I will have to find another way to do it. 

Mark Friedman

unread,
Jan 23, 2025, 12:55:27 PMJan 23
to blo...@googlegroups.com
On Wed, Jan 22, 2025 at 5:45 PM Josue Miguel <josue...@gmail.com> wrote:
Thanks for the responses!  I got confused easily because it was difficult for me to understand how mutators works ; also I only wanted to test mutators quickly to see if it was worth to implement in my project prototype.

Mutators are certainly one of the more complex areas of Blockly to understand and the compose/decompose based mutator UI is especially so.

I see that I could simplify the code if I implement a custom plus and minus button, instead of using the subblocks, but because image fields are not serializable, I think it won't be possible to save the block with the workspace save function. So probably, I will have to find another way to do it. 

The fact that image fields are not serializable should not normally be an issue.  The blocks using the image fields will, themselves, still be serialized and saved.  The image field doesn't normally need to be serialized because the block that uses it will specify the URL of the image to be used for the field.  

The only case where you might need explicit serialization of an image field would be if you are programmatically changing the URL for the field after the block and field are created.  If that is the case for you you can create your own serializable image field class as a subclass of FieldImage, similar to the case with FieldLabel and FieldLabelSerializable.

-Mark

Reply all
Reply to author
Forward
0 new messages