How to set variable block to a list

718 views
Skip to first unread message

Liam Tran

unread,
Jun 3, 2021, 7:16:42 PM6/3/21
to Blockly

Hi guys I am new to Blockly. I am facing a problem of cannot assign a value to variable.
I have 2 JSON Array for example foos and circles that already existed from my program.

var foos = [{"prop1":"value1", "prop2":"value2" }, { "prop1":"value3",  "prop2":"value4"}];
   
var circles = [{ "prop1":"value1", "prop2":"value2", "prop3":"value3"},
                        { "prop1":"value4", "prop2":"value5", "prop3":"value6"}];


I wrote a block with dropdown of list of objects user want to get. I created afterwards a variable and named it "fooList". I tried to set "fooList" Variable with the existing "foos" json array I already defined in my program above but it didn't work. (See foto below) The program cannot generate the code. I also tried to return function(block) with a simple string like "Hello". It also didn't work. So I guess it's not because of json Array but the connection between set Variable block and my block is somehow not working.  Can some one helps me with this problem?
My block looks like this:

Blockly.Blocks['listofobjects_dropdown'] = {

init: function() {
  var options = [
   ['get list of foos', 'FOOS'],
   ['get list of circle', 'CIRCLES']
  ];

  this.appendDummyInput()
  .appendField(new Blockly.FieldDropdown(options), 'MODE');
  this.setOutput(true, "Array");
  this.setColour(266);
}};

Blockly.JavaScript["listofobjects_dropdown"] = function(block) {
  var variable_variable = Blockly.JavaScript.variableDB_.getName(
    block.getFieldValue("MODE"),
    Blockly.Variables.NAME_TYPE
  );
  var code = null;
  if (variable_variable == "FOOS") {
    code = `${foos}\n`;
    return code;
  } else if (variable_variable == "CIRCLES") {
    code = `${circles}\n`;
    return code;
  }
 
  return code;
};



The second problem I got is syntax error by generating only the get List of Dropdown Objects. (See Foto below) The generated code look like this after I choosed "foos":

[object Object],[object Object] ;

 
Thanks for reading and I hope someone can help me with the problems. :)
SyntexErrorFromGetListBlock.JPG
BlocklySetFooList.JPG

Beka Westberg

unread,
Jun 4, 2021, 4:23:40 PM6/4/21
to blo...@googlegroups.com
Hello,

I think this is actually a pretty simple fix! My guess is you don't need to wrap your dropdown field value in the getName() call. If you check here you can see that getName is meant to keep identifiers from colliding within your generated code. So unless you're doing something like the below you shouldn't need it:
```
// Observe how the name is getting appended to the code
code += Blockly.JavaScript.variableDB_.getName(
    block.getFieldValue("MODE"),
    Blockly.Variables.NAME_TYPE
  );
```

That means that your updated code generator will look like:
```
Blockly.JavaScript["listofobjects_dropdown"] = function(block) {
  var mode = block.getFieldValue("MODE")
  if (mode == "FOOS") {
    return `${foos}\n`; // Simplified returns as well.
  } else if (mode == "CIRCLES") {
    return `${circles}\n`;
  }
};
```

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

--
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/58d7630a-10d2-408b-ba8e-bcefe2e71aeen%40googlegroups.com.

Liam Tran

unread,
Jun 4, 2021, 10:04:29 PM6/4/21
to Blockly
Thanks Beka for your suggestion! Unfortunately I still didn't fix the problem. The problem is when I create a variable and named it for example "fooList". I tried to set "fooList" with the listofobjects_dropdownblock it didn't generate any code. (See foto bellow). On the XML I wrote this: <category name="Variables" custom ="VARIABLE" colour="%{BKY_VARIABLES_HUE}"> </category>

I tested a bit around and what weird is the  Blockly.JavaScript["listofobjects_dropdown"] = function(block) only generate code when I return null;
The generated code look like this: var fooList; fooList = 0; But when the return is other then null then no code is generated and I don't want to return null. I don't know if I missed something or why my code cannot be generated.
BlocklySetFooList.JPG

Beka Westberg

unread,
Jun 5, 2021, 10:28:26 AM6/5/21
to blo...@googlegroups.com
Hmm that is definitely weird. Could you answer a few questions so I'm sure I understand the situation correctly?

> I tried to set "fooList" with the listofobjects_dropdownblock it didn't generate any code.

Could you post the call you are using to generate the code? Eg it should be something similar to Blockly.JavaScript.workspaceToCode(workspace)

> On the XML I wrote this: <category name="Variables" custom ="VARIABLE" colour="%{BKY_VARIABLES_HUE}"> </category>

This is in the toolbox xml correct?

> I tested a bit around and what weird is the  Blockly.JavaScript["listofobjects_dropdown"] = function(block) only generate code when I return null;

Where are you returning null from? Like from inside your block-code generator? Could you give an example?

---

One thing I also just noticed reading through this again is that you're dealing with a value block (ie a block with an output) so you need to return an array containing the code string and your precedence, rather than just your code string. Maybe that will fix the issue!

```
Blockly.JavaScript["listofobjects_dropdown"] = function(block) {
  var mode = block.getFieldValue("MODE")
  if (mode == "FOOS") {
    return [`${foos}`, Blockly.JavaScript.ORDER_NONE];

  } else if (mode == "CIRCLES") {
    return [`${circles}`, Blockly.JavaScript.ORDER_NONE];
  }
};
```

I hope that helps!
--Beka

Liam Tran

unread,
Jun 5, 2021, 11:33:14 AM6/5/21
to Blockly
Thank you so much for your suggestion. It finally works after I changed it to return [`${foos}`, Blockly.JavaScript.ORDER_NONE];

I have another question. Is there any way that I can set variable inside my program without user has to define it themself?

For example: set fooList = [{"prop1":"value1", "prop2":"value2" }, { "prop1":"value3",  "prop2":"value4"}];

I want to give the user in Toolbox a list of Variable with the value that already pre defined in the program. User just needs to use the Variable it without having to setVariable. How could I do that? :)

Beka Westberg

unread,
Jun 6, 2021, 5:34:53 PM6/6/21
to blo...@googlegroups.com
Yeah absolutely!

The thing to remember is that at the base level, Blockly is just a really fancy program for generating code strings. So you can have your blocks return whatever code strings you want (eg setting variables). And you can also modify the code string after you receive it from Blockly.

Here's a really basic example of something you could do:
1) Have a block like the below, with the below generator.
fooList.png
```
Blockly.JavaScript['block_type'] = function(block) {
  return ['fooList', Blockly.JavaScript.ORDER_NONE];
};
```

2) Add info about `fooList` to the beginning of your generatorated code string.
```
var code = Blockly.JavaScript.workspaceToCode(myWorkspace);
code = 'var fooList = [{"prop1":"value1", "prop2":"value2" }, { "prop1":"value3",  "prop2":"value4"}];\n' + code;
```

3) Evaluate it.
```
eval(code);
```

There are other ways you could do it depending on what environment you're evaluating the code string in (eg if you're using an interpreter). But I hope that gives you an idea of where to start!

Best wishes,
--Beka

Liam Tran

unread,
Jun 7, 2021, 3:15:15 AM6/7/21
to Blockly
Thank you so much for your clear explaination Beka! :) It works perfectly. :) I have another question about hiding/showing user creating function blocks when they don't currently work on that function blocks.

When the users create too many functions on the Workspace, its gonna look unclear at some point. See my foto as an example. If a user is now working on the "thirdFunction", he/she could click on the "thirdFunction" block in Toolbox and the "thirdFunction" blocks show up in Workspace. Afterwards he/she thinks that they need to edit the "secondFunction" then they could click on the "secondFunction" and the "thirdFunction" and "firstFunction" would disappear from the Workspace. At the end. When user click on "code generate", the "firstFunction", "secondFunction" and "thirdFunction" would all be generated, and not just one of the the Function on the current Workspace. Is there a way that I can do that or if not is there other ways to pursue the purpose of making a clear workspace for user? The functions that user create need to be reuseable in another functions.

Have a good day and best wishes, Liam
FunctionHideBlockFromWorkspace.JPG

Beka Westberg

unread,
Jun 7, 2021, 5:41:41 PM6/7/21
to blo...@googlegroups.com
Hello,

You might be able to do this by serializing and deserializing the functions whenever you want to hide/show them. And I think you could detect the clicks on blocks using the events system, if you attached your click listener to the flyout (instead of the main workspace).

However, Blockly already provides a nice way for the user to organize their workspace, which is collapsing blocks. So you'll have to decide whether serializing and deserializing is worth the trouble hehe.
collapse-block.gif


Reply all
Reply to author
Forward
0 new messages