Unable to save

126 views
Skip to first unread message

bruh 9000

unread,
Mar 14, 2024, 12:04:58 AM3/14/24
to Blockly
https://developers.google.com/blockly/guides/configure/web/serialization

Using the above reference, I added

function saveButton() {
            const state = Blockly.serialization.workspaces.save(myWorkspace);
          }

as a script for a button and I get the following error when it is pressed. I want to be able to save the text to a variable (and download it for the user)

ERROR

Cannot read properties of undefined (reading 'workspaces')

TypeError: Cannot read properties of undefined (reading 'workspaces')

    at saveButton (http://localhost:8081/:17:49)

    at HTMLButtonElement.onclick (http://localhost:8081/:13:56)


Christopher Allen

unread,
Mar 14, 2024, 12:15:59 PM3/14/24
to blo...@googlegroups.com
Hi bruh,

Using the above reference, I added

function saveButton() {
            const state = Blockly.serialization.workspaces.save(myWorkspace);
          }

as a script for a button and I get the following error when it is pressed. I want to be able to save the text to a variable (and download it for the user)

Assuming that you have a Workspace stored in a variable called myWorkspace then that indeed looks correct to me. 
 

ERROR

Cannot read properties of undefined (reading 'workspaces')

TypeError: Cannot read properties of undefined (reading 'workspaces')

    at saveButton (http://localhost:8081/:17:49)

    at HTMLButtonElement.onclick (http://localhost:8081/:13:56)


This is curious because it suggests that Blockly.serialization.workspaces is undefined, which should not be the case.

Can you check what version of the blockly package you are using, and show us how you are importing it?

Thanks,

Christopher

bruh 9000

unread,
Mar 14, 2024, 8:52:42 PM3/14/24
to Blockly
I don't have workspace saved in a var called myWorkspace

I imported it with `npx @blockly/create-package app hello-world`

Christopher Allen

unread,
Mar 15, 2024, 6:31:33 AM3/15/24
to blo...@googlegroups.com
Hi bruh,
 
I don't have workspace saved in a var called myWorkspace

I imported it with `npx @blockly/create-package app hello-world`

OK, so in the sample app that is created by that command, if you look in src/index.js, you'll see the line

const ws = Blockly.inject(blocklyDiv, {toolbox});


which creates a variable named ws that contains the main Workspace.  So that would be one reason that the line

const state = Blockly.serialization.workspaces.save(myWorkspace);

will not work: you'd need to use ws and not myWorkspace.  But the error message you reported was not "Uncaught ReferenceError: myWorkspace is not defined" but rather "Cannot read properties of undefined (reading 'workspaces')", and (I now realise) this must be caused caused by Blockly not being defined.  Have you forgotten to import it in the file where you have written the const state = … ?  Have a look at src/serialization.js for an example of how to import Blockly and use Blockly.serialization.workspaces.save().


Best wishes,

Christopher

bruh 9000

unread,
Mar 20, 2024, 9:07:22 PM3/20/24
to Blockly
Thanks for the reply.

I tried doing that but I am unable to import blockly with

import * as Blockly from 'blockly/core';

as I am making this button in index.html

Maribeth Moffatt

unread,
Mar 20, 2024, 9:36:37 PM3/20/24
to Blockly
Hello,

Since you're using the sample app which is built with webpack, things will be simpler if you only write JavaScript in JavaScript files, not in the index.html. You can make the button in html, and attach the event listener to it in a js file.

There are ways to get access to Blockly in HTML, but you risk complicating things and possibly loading too many copies of Blockly if you start to mix how you import it.

Best,
Maribeth

bruh 9000

unread,
Mar 21, 2024, 11:33:22 PM3/21/24
to Blockly
Hello,

I attempted to do it in another JS file but was unable to successfully do so. Would you be able to provide an example / demonstration?

Maribeth Moffatt

unread,
Mar 22, 2024, 12:19:09 PM3/22/24
to Blockly
It would be easiest if you shared your code so we can help spot what might be going wrong.

For an example of how to save, you've already seen the serialization docs. If you're looking for an example of how to add a click handler to a button, MDN is my go-to resource; here's their docs on event handlers with examples. You'll want to place the serialization code inside your event handler.

Best,
Maribeth

bruh 9000

unread,
Mar 22, 2024, 7:26:41 PM3/22/24
to Blockly
Sure,

https://github.com/bruh-9000/moddBlockly/compare/main...save-button

This is my code that is working on the save button. I did actually successfully get the save button working, but I am unable to get the load button working.

Cannot read properties of undefined (reading 'toLowerCase')

TypeError: Cannot read properties of undefined (reading 'toLowerCase')

    at $.Names$$module$build$src$core$names.equals (webpack-internal:///./node_modules/blockly/blockly_compressed.js:728:395)

    at VariableMap$$module$build$src$core$variable_map.getVariable (webpack-internal:///./node_modules/blockly/blockly_compressed.js:1040:360)

    at VariableMap$$module$build$src$core$variable_map.createVariable (webpack-internal:///./node_modules/blockly/blockly_compressed.js:1036:378)

    at WorkspaceSvg$$module$build$src$core$workspace_svg.createVariable (webpack-internal:///./node_modules/blockly/blockly_compressed.js:1048:464)

    at WorkspaceSvg$$module$build$src$core$workspace_svg.createVariable (webpack-internal:///./node_modules/blockly/blockly_compressed.js:1088:380)

    at VariableSerializer$$module$build$src$core$serialization$variables.load (webpack-internal:///./node_modules/blockly/blockly_compressed.js:1237:578)

    at reader.onload (webpack-internal:///./src/index.js:103:20)



I keep getting this error when I load a download, such as

{"blocks":{"languageVersion":0,"blocks":[{"type":"triggers","id":"^P}o3PZ+%*/Z`WH5=@P%","x":47,"y":16,"next":{"block":{"type":"secondtick","id":"?/azR@E}ejxUiR_it2@7"}}},{"type":"script","id":":yIeU8b:_zuj{=y{4,_m","x":45,"y":121,"next":{"block":{"type":"sendchatmessage","id":"Y+}y8m$[pw?.[oFg4~ZJ","inputs":{"message":{"shadow":{"type":"text","id":")u[IdKM3FiNGE@o]O`^r","fields":{"TEXT":"This is a test!"}}}}}}}]}}

(I do have custom blocks, you can see them at https://bruh-9000.github.io/moddBlockly/, but this link does not have any of the features for the save and load buttons right now since those aren't finished)

Mark Friedman

unread,
Mar 22, 2024, 7:52:34 PM3/22/24
to blo...@googlegroups.com
It looks to me like you want to load a workspace, but are using the serializer for variables (i.e. Blockly.serialization.variables.VariableSerializer) rather than the serializer for workspaces (i.e. Blockly.serialization.workspaces.load).  Maybe take another look at the serialization docs.

Hope this helps.

-Mark


--
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/c91da113-9d02-4f68-a3f2-6cc276ffcd5fn%40googlegroups.com.

bruh 9000

unread,
Mar 22, 2024, 8:14:59 PM3/22/24
to Blockly
I tried changing it to Blockly.serialization.workspaces.load(fileContent, ws); in

const loadButton = document.querySelector("#loadButton");

loadButton.addEventListener("click", () => {
  const input = document.createElement('input');
  let fileContent;
  input.type = 'file';
  input.accept = '.txt'; // Specify the file types you want to accept
  input.onchange = function(event) {
      const file = event.target.files[0];
      const reader = new FileReader();
      reader.onload = function(event) {
        fileContent = event.target.result;
       
        Blockly.serialization.workspaces.load(fileContent, ws);
      };
      reader.readAsText(file);
  };
  input.click();
});

And it just leaves the workspace blank. I did try looking at the documentation earlier, but didn't understand it fully so went here. Sorry if my questions are easily answered by the documentation, I am just very new to Blockly.

Maribeth Moffatt

unread,
Mar 22, 2024, 8:57:12 PM3/22/24
to Blockly
Hi, Mark is correct, so after fixing that we're one step closer.

The `load` function expects data in the same format that `save` gave it to you. Whatever transformations you make to the saved data, you need to undo them before you try to load it. For example in your save function, you JSON.stringify the data. That means you need to JSON.parse the string before you can load it. You also called `encodeURIComponent` on it, so you may need to `decodeURIComponent` as well.

What does the actual file content you're trying to load look like? Logging that before you call `load` will likely be helpful. Right before load, you want to make sure it looks like the original JSON data that Blockly gave you from `save`. Sharing an example of the file contents here would also be helpful for further debugging.

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