Nesting Custom Blocks

601 views
Skip to first unread message

Khush Ramdev

unread,
Sep 4, 2021, 8:02:36 AM9/4/21
to Blockly
So i am working on an assignment. but i cant seem to figure out how to made do work of nested elements 

Blockly.Blocks['ask_me_a_question'] = {
  init: function() {
    this.appendDummyInput()
        .appendField(new Blockly.FieldLabelSerializable("Ask me a Question"), "QUESTION");
    this.appendStatementInput("Ask me a question")
        .setCheck(null)
        .appendField(new Blockly.FieldDropdown([["What is the date today?","DATE"], ["What is the time now?","TIME"], ["How are you?","HEALTH"], [" What is JavaScript?","JAVASCRIPT"], ["What is your name?","NAME"]]), "QUESTIONS");
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(330);
 this.setTooltip("");
 this.setHelpUrl("");
  }
};

Blockly.JavaScript['ask_me_a_question'] = function(block) {
  var dropdown_questions = block.getFieldValue('QUESTIONS');
  var statements_ask_me_a_question = Blockly.JavaScript.statementToCode(block, 'ask_me_a_question');
  // TODO: Assemble JavaScript into code variable.
  var code = `var dropdown_question = "${dropdown_questions}";`;
  return code;
};

above code is used to create a dropdown 

Blockly.Blocks['bot'] = {
  init: function() {
    this.appendDummyInput()
        .appendField("BOT");
    this.appendStatementInput("question")
        .setCheck("ask_me_a_question");
    this.setInputsInline(true);
    this.setColour(230);
 this.setTooltip("");
 this.setHelpUrl("");
  }
};

Blockly.JavaScript['bot'] = function(block) {
  var statements_question = Blockly.JavaScript.statementToCode(block, 'question');
  // TODO: Assemble JavaScript into code variable.
  var code = `var statements = "${statements_question}";`;
  return code;
};

i need to nest to ask_me_a_question block into this and output accordingly. but i am thrown an error of unexpected identifier here 

function runcode() {
  // Generate JavaScript code and run it.
  var geval = eval;
  try {
    geval(Blockly.JavaScript.workspaceToCode(workspace)); //error here 
  } catch (e) {
    console.error(e);
  }
  redrawUi();
}

as I am a newbie I am really confused how to solve this issue.
Any help would be appreciated 
Thank you

Faraz Firoz

unread,
Sep 4, 2021, 10:16:52 AM9/4/21
to Blockly
In function run() code do like this
function run() {
  Blockly.JavaScript.addReservedWords('code');
  var code = Blockly.JavaScript.workspaceToCode(workspace);
  try {
    eval(code);
  } catch (e) {
    alert(e);
  }
}

Jason Schanker

unread,
Sep 4, 2021, 8:49:23 PM9/4/21
to Blockly
Hi,

Is this all of the code?  If so, workspace will not be defined.  You can fix this by using Blockly.getMainWorkspace() instead, but I'm not sure if this is the issue you're encountering.  For reference, a number of people have asked questions about this assignment in the past:

https://groups.google.com/g/blockly/c/ewXFprydsJo/m/4DwyQ0OXAgAJ
If you're allowed to share a link to the assignment, it would help us answer questions about it that may come up in the future.

Best,
Jason

Khush Ramdev

unread,
Sep 5, 2021, 5:26:58 AM9/5/21
to Blockly
thank you for sharing that links it helped me complete the assignment. I am not sure if I am allowed to share the assignment publicly.  
but https://groups.google.com/g/blockly/c/1fmRCn0XeOA/m/WkeAxg8hAgAJ answer was the key to my answer. I was unable to access the parent elements basically and it sorted it out. Apart from documentation are there any resources for learning Blocky? because I might need them.

Jason Schanker

unread,
Sep 5, 2021, 11:32:50 AM9/5/21
to Blockly
Great, in addition to the Developer Guide at https://developers.google.com/blockly/guides/get-started/web , here are a couple of other resources that I know of that might help:

Blockly Codelabs: https://blocklycodelabs.dev/
2021 Blockly Developer Summit (also can probably find related videos on specific topics from previous summits): https://www.youtube.com/watch?v=uuOmrYipPeA&list=PLSIUOFhnxEiCjoIwJ0jAdwpTZET73CK7d&index=1

Jason Schanker

unread,
Sep 5, 2021, 7:32:11 PM9/5/21
to Blockly
Just to follow up, for some reason when I first answered your question, I wasn't thinking you were adding blocks to the workspace so I just quickly glanced over the block/generator definitions.  But yes, given your previous setup if you were to attach an ask me a question block to a bot block, you'd generate the following code:

var statements = "  var dropdown_question = "DATE";";

And DATE would therefore be the unexpected identifier since it unexpectedly follows the close of a string literal.  For future debugging, typing Blockly.JavaScript.workspaceToCode(Blockly.getMainWorkspace()) in the console may help so you can see the generated code to help you identify the problem.

Some notes/issues, which you may have realized/addressed:

1.   Blockly.JavaScript.statementToCode(block, inputName) evaluates to the string of code returned by the generator of the block attached to the input named inputName.  If there is no input with that name or there is no attached block, the empty string will be returned.  So Blockly.JavaScript.statementToCode(block, 'ask_me_a_question'); will be the empty string because there is no input named 'ask_me_a_question' for the  'ask_me_a_question' block.   There is an input named Ask me a question, but the code for that would be the code generated by the attached statement block and would not incorporate its own field value if the attached block's generator didn't.
2. A value/statement input contains a place where a block can be placed that may also contain text and fields.  When you simply want a row for field values/text, you can use a dummy input as a placeholder instead.  And as shown in the post you linked to, you can append multiple fields to the same dummy input.  This assures that they all appear on the same line.  Alternatively, you could also use multiple dummy inputs and set the inputs inline by adding this.setInputsInline(true) in the init function of the block definition.  Here, you probably don't want a statement input for the ask_me_a_question block since you don't want a space for a statement block.
3. If the new return value from the generator for the ask_me_a_question block is ${dropdown_questions}, i.e., its field value, then be aware that this string will become part of the code when it's not attached to a Bot block.  To remedy this, you may want to check if it's attached to a parent bot block before generating code from it:

Blockly.JavaScript['ask_me_a_question'] = function(block) {
  return this.getPreviousBlock() && this.getPreviousBlock().type === 'bot' ? block.getFieldValue('QUESTIONS') : "";
};

Hope this helps as you learn more about Blockly.
Message has been deleted

Khush Ramdev

unread,
Sep 13, 2021, 7:13:15 AM9/13/21
to Blockly
Thanks Jason you follow-up email helped me to understand some more concepts of Blockly.
Is there any detailed documentation on custom block making which I can refer to? google custom block section is just one html page :(

Jason Schanker

unread,
Sep 13, 2021, 2:09:50 PM9/13/21
to Blockly
Hi,

Is the sidebar navigation showing up for you?  There are a number of links there under the Creating Blocks section, providing extensive guidance.  I'm including (most of) them below in case you're not able to access them:

https://developers.google.com/blockly/guides/create-custom-blocks/define-blocks
https://developers.google.com/blockly/guides/create-custom-blocks/localize-blocks
https://developers.google.com/blockly/guides/create-custom-blocks/generating-code

There are also additional links on built-in fields and custom fields.

Additionally, the Block Factory can be helpful:


It allows you to create block definitions by dragging/dropping/modifying blocks!

Best,
Jason
Reply all
Reply to author
Forward
0 new messages