Having trouble restoring the state of dynamic fields

68 views
Skip to first unread message

Roman

unread,
Jun 8, 2022, 12:41:20 AM6/8/22
to Blockly
Hello,
I am trying to make a dynamic block that allows for a gear icon to be clicked to open up a menu of checkboxes/inputs to configure. I need to save and restore the workspace for my application.

I am coming across this error when I try to load in a workspace with XML

image_2022-06-07_222951749.png

I understand why the issue is occurring because by default the block doesn't have the fields the "more options" icon has to be clicked to make the fields.

image_2022-06-07_223258004.png
image_2022-06-07_223331772.png

Here is the code I have come up with so far:
image_2022-06-07_223954146.png
Is this the correct approach to this? I don't think I understand mutators and how to save these fields across states correctly.
Thanks
code.txt

Neil Fraser

unread,
Jun 8, 2022, 6:24:35 AM6/8/22
to blo...@googlegroups.com
Great question, and you are almost there.  The issue is that Blockly has two incompatible save formats, and each requires different hooks.  You are using XML, but your hooks (saveExtraState/loadExtraState) are for JSON.  So either use JSON as your save format, or use the XML hooks (mutationToDom/domToMutation).

If you want to use XML, then a good block to look at is math_number_property.  It is an interesting block because the second input appears or disappears depending on whether the dropdown is set to "divisible by" or not.  At least that's what the user sees.  In practice the existence of this input is due to a mutation.

If you load this XML:
<xml xmlns="https://developers.google.com/blockly/xml">
  <block type="math_number_property"></block>
</xml>
Then you get this block:
Screen Shot 2022-06-08 at 11.58.35.png

But if you load this XML:
<xml xmlns="https://developers.google.com/blockly/xml">
  <block type="math_number_property">
    <mutation divisor_input="true"></mutation>
    <field name="PROPERTY">DIVISIBLE_BY</field>
  </block>
</xml>
You get this block:
Screen Shot 2022-06-08 at 12.02.30.png
The code for this is here:

So what you need to do is add a pair of 'mutationToDom' and a 'domToMutation' functions to your block.  If it's just a binary flag that needs to be stored ("no options" vs "more options") then it's really simple:
  mutationToDom: function() {
    const container = xmlUtils.createElement('mutation');
    const moreOptions = YOUR CODE TO DETERMINE IF 'MORE OPTIONS' IS ENABLED;
    container.setAttribute('more_options', Boolean(moreOptions));
    return container;
  },
  domToMutation: function(xmlElement) {
    const moreOptions = (xmlElement.getAttribute('moreOptions') === 'true');
    YOUR CODE TO CREATE MORE OPTIONS IF moreOptions IS TRUE.
  },

Using mutationToDom, you can encode any data you want on the XML mutation container.  Any format, doesn't matter.  But then it's your responsibility to be able to parse and read your data back in domToMutation.

--
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/7a11d91f-435d-4deb-938d-7b03c11040dfn%40googlegroups.com.


--
Reply all
Reply to author
Forward
0 new messages