How do I join / disconnect two blocks together from JavaScript?

2,802 views
Skip to first unread message

phil cleaver

unread,
Nov 16, 2014, 10:08:01 PM11/16/14
to blo...@googlegroups.com
Hi,

I need to manipulate my Blockly blocks programmatically.  So far I have been deconstructing to XML then reformatting it and regenerating the workspace from the XML.  It works, but it's painful and I've been trying instead to manipulate the workspace directly.

I see that it's easy to set a field value using block_ref.setFieldValue(name, value). Selecting, duplicating and deleting blocks is just as easy, but I cannot see how to join blocks together or disconnect them (I was looking for block.setValue or setValueValue??).

It looks like it has something to do with setParent and connections, but it's turning out to be a bit harder than I first thought.  

Many Thanks

Phil

Martyn Eggleton

unread,
Nov 17, 2014, 3:24:48 AM11/17/14
to phil cleaver, blo...@googlegroups.com
Hi. There may be a way to do what you are suggesting but I don't know it. But there have just been commits about importing and exporting in json rather than XML. That may give you a work around.

phil cleaver wrote:
--
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.
For more options, visit https://groups.google.com/d/optout.
Sent Using Firefox OS

Mark Friedman

unread,
Nov 17, 2014, 4:02:29 PM11/17/14
to blo...@googlegroups.com
I believe that Block.unplug() is what you want.  If you have a block in a variable named blk then 'blk.unplug(true, true)' should disconnect the block from its parent and move the block a little ways away.

-Mark

--

phil cleaver

unread,
Nov 18, 2014, 5:54:32 AM11/18/14
to blo...@googlegroups.com
thanks Mark, that works great, is it just as easy to join them together again?

Phil

Mark Friedman

unread,
Nov 18, 2014, 2:29:43 PM11/18/14
to blo...@googlegroups.com
It's not quite as easy connect them, since you have to know which input connection (i.e. socket) you want to join them at.  If you know the input Connection object (as cnxn) and the block that you want to plug into that connection (as blk) then you can do 'cnxn.connect(blk.outputConnection)'.  There are a number of ways to get the connection.  One way is by referencing the input by name.  If you look at the various block definitions in the .../blocks directory you'll see that each input for a particular type of block has a string name, which is usually specified in a call to appendValueInput, appendField or interpolateMsg.  Once you have the name of the input that you want to plug into you can get its Input object using 'blk.getInput(name)' and then the corresponding Connection object via 'inpt.connection'.

As a concrete example, if you have an arithmetic operation (e.g. '+') block (as aBlk) and a number block (nBlk) you could plug the number block into the first input socket via 'aBlk.getInput('A').connection.connect(nBlk.outputConnection)'.  Similarly, if you have a string length block (as lBlk) and a text string block (as tBlk) you can connect them using 'lBlk.getInput('VALUE').connection.connect(tBlk.outputConnection)'.

Hope this helps.

-Mark

phil cleaver

unread,
Nov 19, 2014, 5:47:08 AM11/19/14
to blo...@googlegroups.com
Thanks Mark,

That really helps, I wasn't really aware how the connectors worked, but that explains it for me. I'll give it a try.

The last little bit of the jigsaw missing is the ability to make a block object from a list of values.  I imagine the Block definition file is used somehow, but I'm not sure how.  : /

Phil

Mark Friedman

unread,
Nov 19, 2014, 2:28:38 PM11/19/14
to blo...@googlegroups.com
Phil,

  What exactly do you mean by "make a block object from a list of values"?  Could you give an example?

-Mark

phil cleaver

unread,
Nov 19, 2014, 11:17:04 PM11/19/14
to blo...@googlegroups.com
Hi Mark,

I'll try to explain what I mean.  Let's assume I just have one block of type text_print on the workspace, lets call this text_print_block.  

workspace XML : <block type="text_print">


I want to generate a text block and attach it to the 'text' value of the print block using Javascript.

the xml of the not-yet created block would look like this:  <block type="text"><field name="TEXT"></field></block>
      
This second block doesn't exist yet so, I'd like to do something like

// make the new block
var new_block = new Block({   
    type = 'text'
});

// populate the new block with data
new_block.setField('text','the text I want to print');

the xml of the new block should now look like this:  <block type="text"><field name="TEXT">the text I want to print</field></block>

// attach the new block to the value of the print block
text_print_block.setValue('TEXT', new_block);

workspace xml should now be :
<block type="text_print" id="2218" inline="false" x="-733" y="-156">
    <value name="TEXT">
      <block type="text" id="2205">
        <field name="TEXT">the text I want to print</field>
      </block>
    </value>
  </block>

I realise that I need to do what you explained yesterday to make the connection, this is pseudo-code to make it easier to grasp.

I hope this makes myself a little bit clearer.

Thanks Mark

Phil

Neil Fraser

unread,
Nov 20, 2014, 1:53:55 AM11/20/14
to blo...@googlegroups.com
Open the console and type:

var parentBlock = Blockly.Block.obtain(Blockly.getMainWorkspace(), 'text_print');
parentBlock.initSvg();
parentBlock.render();

var childBlock = Blockly.Block.obtain(Blockly.getMainWorkspace(), 'text');
childBlock.setFieldValue('Hello', 'TEXT');
childBlock.initSvg();
childBlock.render();

var parentConnection = parentBlock.getInput('TEXT').connection;
var childConnection = childBlock.outputConnection;
parentConnection.connect(childConnection);


That last line could equally well be childConnection.connect(parentConnection), order doesn't matter.

phil cleaver

unread,
Nov 21, 2014, 3:05:59 AM11/21/14
to blo...@googlegroups.com, ro...@neil.fraser.name
You're a rockstar neil - thanks!!

Phil
Message has been deleted

phil cleaver

unread,
Nov 22, 2014, 5:42:01 AM11/22/14
to blo...@googlegroups.com, ro...@neil.fraser.name
Got it working and connecting blocks from JS which is awesome, but am now having difficulty getting a block to tell me it's type,
i.e. parentBlock below should tell me that it's a 'text_print'.  

parentBlock.type returns true.

What am I missing here?

Thanks

Phil



On Thursday, 20 November 2014 13:53:55 UTC+7, Neil Fraser wrote:

Neil Fraser

unread,
Nov 22, 2014, 1:42:33 PM11/22/14
to phil cleaver, blo...@googlegroups.com
I don't know what's wrong.  It works for me:


var parentBlock = Blockly.Block.obtain(Blockly.getMainWorkspace(), 'text_print');
parentBlock.initSvg();
parentBlock.render();
alert(parentBlock.type);

-> alerts "text_print"

On 22 November 2014 at 02:42, phil cleaver <phil_c...@hotmail.com> wrote:
Got it working and connecting blocks from JS which is awesome, but am now having difficulty getting a block to tell me it's type,
i.e. parentBlock below should tell me that it's a 'text_print'.  

parentBlock.type returns true.

What am I missing here?

Thanks

Phil



phil cleaver

unread,
Nov 22, 2014, 11:41:29 PM11/22/14
to blo...@googlegroups.com, phil_c...@hotmail.com, ro...@neil.fraser.name
Sorry to waste your time there Neil, you're totally right, I guess I'd had a really long day.

Soz

Phil

phil cleaver

unread,
Nov 23, 2014, 11:20:16 PM11/23/14
to blo...@googlegroups.com, phil_c...@hotmail.com, ro...@neil.fraser.name
If anyone is looking at this post for reference, here is how I added an entry to a mutator.

// make the mutator
var mutator = Blockly.Block.obtain(Blockly.getMainWorkspace(), 'text_join'); mutator.initSvg(); mutator.render();

// add a new item
var new_input = mutator.appendInput_(1,'ADD' + mutator.inputList.length);
mutator.itemCount_ = mutator.inputList.length;

this new_input can be used to create a connection to this new mutator item.

Happy mutating

Phil

Sujil V.S

unread,
Jun 10, 2016, 3:18:06 AM6/10/16
to Blockly, ro...@neil.fraser.name
If there are no input i.e.:
Blockly.Blocks['node_head'] = {
  init: function() {
    this.appendDummyInput()
        .appendField("Node Head");
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(50);
    this.setTooltip('');
    this.setHelpUrl('http://www.example.com/');
  }
};

How we can connect them together?
PFA,

Julian F.

unread,
Oct 30, 2020, 4:59:07 AM10/30/20
to Blockly

Hey, did you solve the problem because I have the same problem!

Beka Westberg

unread,
Oct 30, 2020, 3:18:25 PM10/30/20
to blo...@googlegroups.com
Hello,

I replied to a question related to this a few days ago (don't worry the thread title was unrelated so you wouldn't have seen it) Here's what I wrote:

Connecting is handled by the Blockly.Connection object, using the connect function. The basic form is `connectionA.connect(connectionB)`.

Accessing connections is done in lots of ways. Blocks can have connections directly attached to them. Eg outputConnectionpreviousConnection, and nextConnection. Inputs can also have connections, which you can access via the connection property. To get at the input itself you can use block.getInput (and some others).

So basically once you figure out how you want to access your connections, you're golden =)

And just so you know, usually it's better to start a new thread, rather than resurrecting an old one. People are more likely to reply to something fresh!

I hope that helps =)
--Beka 

Julian F.

unread,
Oct 30, 2020, 4:13:10 PM10/30/20
to Blockly
Thank you!

Could you make an example on how to connect to print_text-Blocks?

I tried
var parentBlock = demoWorkspace.newBlock('text_print');
    parentBlock.initSvg();
    parentBlock.render();
    var childBlock = demoWorkspace.newBlock('text_print');
    childBlock.initSvg();
    childBlock.render();
    parentBlock.outputConnection.connect(childBlock.previousConnection);

but get this error:
TypeError: null is not an object (evaluating 'parentBlock.outputConnection.connect')

Can you help me?
Julian

Beka Westberg

unread,
Oct 30, 2020, 4:37:07 PM10/30/20
to blo...@googlegroups.com
Oh yeah that's a common issue! Stack blocks - like the print blocks - have "previous connections" and "next connections" (aka top and bottom connections) because they're meant to emulate statements which are run sequentially. This is opposed to row blocks - like the arithmetic blocks - which have "out connections" and "input connections" because they're meant to emulate expressions which evaluate to values.

So instead of using .outputConnection you'll want to use .nextConnection:
parentBlock.nextConnection.connect(childBlock.previousConnection);

I hope that helps!
--Beka

Julian F.

unread,
Oct 31, 2020, 3:22:04 AM10/31/20
to Blockly
Thanks Beka!!

You saved my day! :)

Message has been deleted

Beka Westberg

unread,
Sep 12, 2023, 4:08:27 PM9/12/23
to blo...@googlegroups.com
Hello!

Could you post this in a new forum thread? Generally it's considered bad practice to respond to old posts (this one is almost 10 years old). Asking new questions in a separate thread makes it easier for people to follow the discussion!

Best,
--Beka

On Tue, Sep 12, 2023 at 12:45 PM aakarsh hajela <aakars...@gmail.com> wrote:
var parentBlock = Blockly.Block.obtain(Blockly.getMainWorkspace(), 'text_print');
parentBlock.initSvg();
parentBlock.render();

In the above code, I am getting "Property 'obtain' does not exist on type 'typeof Block' "

I am trying to connect blocks programmatically one after the other by  using their previousConnection and nextConnection functions. 

I tried the below code:

var parentBlock = Blockly.getMainWorkspace().newBlock(block_name1);
parentBlock.initModel();
var childBlock = Blockly.getMainWorkspace().newBlock(block_name2);
childBlock.initModel();
var parentConnection = parentBlock.getInput(input_name).connection;
var childConnection = childBlock.previousConnection;
parentConnection.connect(childConnection);

This loads all the blocks I need but without the connections.
Reply all
Reply to author
Forward
0 new messages