Typing checking not working on my simple example project

288 views
Skip to first unread message

Chris Ainsley

unread,
Oct 19, 2019, 8:48:57 PM10/19/19
to Blockly
Hello,

I just started look at Blockly recently, and I am currently trying to understand how the type validation works.

In the attached blockly block definitions, I have a block called "apple_container" which is designed to contain statements, and has been configured only to accept statements of type "apple". I also create a statement of type "orange".

I don't understand why the Blockly editor is not restricting the user from adding oranges to the apples statement block, when it clearly states that only items of type "apple" are acceptable.

Do I need to call some code in my page to enable type checking?

Obviously, I'm a beginner, so I imagine I'm missing something here.

Chris


Blockly.Blocks['apple_container'] = {
  init
: function() {
   
this.appendDummyInput()
       
.appendField("Apple Container");
   
this.appendStatementInput("apples")
       
.setCheck("apple");
   
this.setColour(230);
 
this.setTooltip("");
 
this.setHelpUrl("");
 
}
};


Blockly.Blocks['apple'] = {
  init
: function() {
   
this.appendDummyInput()
       
.appendField("Apple");
   
this.setPreviousStatement(true, null);
   
this.setNextStatement(true, null);
   
this.setColour(230);
 
this.setTooltip("");
 
this.setHelpUrl("");
 
}
};


Blockly.Blocks['orange'] = {
  init
: function() {
   
this.appendDummyInput()
       
.appendField("Orange");
   
this.setPreviousStatement(true, null);
   
this.setNextStatement(true, null);
   
this.setColour(230);
 
this.setTooltip("");
 
this.setHelpUrl("");
 
}
};

Coda Highland

unread,
Oct 19, 2019, 10:34:14 PM10/19/19
to blo...@googlegroups.com
Blocks don't have types. Connections have types. You'll need to have apple's previous statement connection check for the "apple" type too. If the two connection checks match, or if either of them is null, then the connection is accepted, otherwise it won't lock in.

/s/ Adam

--
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/8c4d9ea2-29d1-4d94-93c5-55cc622d8586%40googlegroups.com.

Beka Westberg

unread,
Oct 20, 2019, 10:31:03 AM10/20/19
to Blockly
This is pretty confusing because connection types are a separate thing from block types (even though they're both called types). 

It makes more sense if you think about connection types in the context they were originally created for, which is type checking of variables, parameters, return values, etc.

To make it so that your 'apple_container' block only accepts apples your block definitions will need to look like so:
Blockly.Blocks['apple_container'] = {
  init
: function() {
   
this.appendDummyInput()
       
.appendField("Apple Container");
   
this.appendStatementInput("apples")
       
.setCheck("apple");
   
this.setColour(230);
 
}
};

Blockly.Blocks['apple'] = {
  init
: function() {
   
this.appendDummyInput()
       
.appendField("Apple");

   
// This makes it so it can go into the statement input.
   
this.setPreviousStatement(true, 'apples');
   
// This makes it so other apples can follow it.
   
this.setNextStatement(true, 'apples');
   
this.setColour(230);

 
}
};

Blockly.Blocks['orange'] = {
  init
: function() {
   
this.appendDummyInput()
       
.appendField("Orange");

   
// This makes it so that it cannot go into the apple input.
   
this.setPreviousStatement(true, 'oranges');
   
// But anything can follow it, including apples.
   
this.setNextStatement(true, null);
   
this.setColour(230);
 
}
};

For more info I actually wrote a whole blog post about typing statement connections.

I hope that helps! If you have any further questions please reply!
--Beka

Vaib Kapoor

unread,
Dec 12, 2019, 1:26:26 PM12/12/19
to Blockly
Hey Beka, I was reading your blog post and just had a question.

I'm trying to build a block that has a statement input for more blocks. I want it to only take in a certain type of block for that statement input, and reject any other block types. I do this by enforcing the type that can go in on the statement input, as well as the previousStatement types and nextStatement types for the blocks that I want to use for that input. This doesn't work however on blocks that don't have types defined, like you outlined in your blog article.

Screen Shot 2019-12-12 at 12.28.06 PM.png

Is there a way to work around this, and have it so blocks that don't have any types defined can't work with that specific block? If so, would this break anything else?

Coda Highland

unread,
Dec 12, 2019, 1:40:49 PM12/12/19
to blo...@googlegroups.com
This has come up in discussion before, actually!

There's been some rumbling ideas to implement a "strict" mode that makes null types only match other null types instead of matching everything. That would accomplish what you're looking for. I don't see any obvious failure modes if you wanted to hack on the Blockly core to implement this. If you put a nice configuration switch on it you might even consider submitting a PR.

I took a different approach in my own project; I iterated over all of the defined blocks and set their connection types to ["default"] if they didn't have any explicit types set. It worked for me, but I confess that monkey-patching it like this is kinda inelegant.

/s/ Adam

--
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.

Beka Westberg

unread,
Dec 12, 2019, 1:45:21 PM12/12/19
to Blockly
Hello!

At the moment there's no easy way to deal with this case :/ I can think of a few bad options for you though

1) Go through and redefine the connections on all existing blocks. If you give everything some place holder value like * they could all connect to eachother. But as long as your statement block doesn't include * they couldn't connect to it.
2) Fork blockly and modify the connection logic, so that non-checking connections only connect if /both/ connections are not checking.
Blockly.Connection.prototype.checkType_ = function(otherConnection) {
 
// I changed the below to be && intead of ||
 
if (!this.check_ && !otherConnection.check_) {
   
// *Both* sides are promiscuous enough that anything will fit.
   
return true;
 
}
 
// ...
};
There's a not insignificant chance that it will break something though.

3. Use an event system listener to disconnect promiscuous blocks, or append warnings to them. This doesn't provide a /great/ user experience, but it's also probably the easiest thing to impliment. 

I hope that gives you some ideas for where to start! If you have any futher questions please reply!
--Beka

Coda Highland

unread,
Dec 12, 2019, 2:01:44 PM12/12/19
to blo...@googlegroups.com
I just realized what I forgot about -- you only want to do (1) or (2) for previous/next connections! If you do it for value connections you'll break things like putting a number as a value for set_variable.

But to the best of my knowledge there are no predefined Blockly blocks that are typed statements, only typed values.

/s/ Adam

--
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.
Reply all
Reply to author
Forward
0 new messages