I\'m trying to use Blockly in an Angular 7 application but I\'m unable to inject the Blockly editor.
I have downloaded the files from https://developers.google.com/b
My answer does not put the XML into the template itself, but rather in a variable which enable the integration without the NO_ERRORS_SCHEMA import in the module.
Step 1: Download the files from Blockly website, and look for:
en.js (Or any language that you want your blockly to be in)
Copy and paste them into src/assets/blockly.
Step 2: In your angular.json file, add the following ( in projects.architect.build.options ):
"scripts": [
"src/assets/blockly/blockly_compressed.js",
"src/assets/blockly/blocks_compressed.js",
"src/assets/blockly/en.js"
]
Step 3: In your component.ts :
import { Component, AfterViewInit } from '@angular/core';
declare var Blockly: any
@Component({
template: `<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>`,
selector: 'app-blockly',
styleUrls: ['./blockly.component.scss']
})
export class BlocklyComponent implements AfterViewInit {
ngAfterViewInit(): void {
const toolbox = `
<xml>
<block type="controls_if"></block>
<block type="controls_whileUntil"></block>
</xml>`;
Blockly.inject('blocklyDiv', { toolbox });
}
}
And that's it !
Use ngx-blockly
instead of blockly
, ngx-blockly is angular port of blockly.
follow the steps explained in npm page
npm install ngx-blockly --save
https://www.npmjs.com/package/ngx-blockly
You should add it to angular.json
firstly.
So angular CLI can build it.
"scripts": [
"../blockly.js"
]
I assume you're using @angular/cli.
Demo
Step 1: Install blockly
npm install blockly
Step 2: Add scripts to angular.json
under the architect node:
"scripts": [
"node_modules/blockly/blockly_compressed.js",
"node_modules/blockly/blocks_compressed.js",
"node_modules/blockly/msg/js/en.js"
]
Step 3: Add NO_ERRORS_SCHEMA
to your AppModule (this is so that you can define custom tags in your components)
@NgModule({
imports: [ BrowserModule, AppRoutingModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
exports: [AppComponent],
schemas: [NO_ERRORS_SCHEMA]
})
export class AppModule {
}
Step 4: Create a Component, declare Blockly as any
, and implement AfterViewInit
so that you can access the blockly-related elements in the DOM:
import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
declare var Blockly: any;
@Component({
selector: 'app-root',
template: `
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
<xml id="toolbox" #toolbox style="display: none">
<block type="controls_if"></block>
<block type="logic_compare"></block>
<block type="controls_repeat_ext"></block>
<block type="math_number"></block>
<block type="math_arithmetic"></block>
<block type="text"></block>
<block type="text_print"></block>
</xml>
`
})
export class AppComponent implements AfterViewInit {
workspace: any;
@ViewChild('toolbox') toolbox: ElementRef;
ngAfterViewInit(): void {
this.workspace = Blockly.inject('blocklyDiv',
{toolbox: this.toolbox.nativeElement });
}
}
NOTE: The Blockly package in NPM is at v1.0, while the latest version is v1.2. To use the latest, just download the library, put it in a known directory, and fix your script references (Step 2).
I was able to setup with the config mentioned below -
install blockly with npm -
npm install git://github.com/google/blockly.git#1.20190419.0
included below files in scripts section of angular.json file -
"scripts": [
"node_modules/blockly/blockly_compressed.js",
"node_modules/blockly/blocks_compressed.js",
"node_modules/blockly/msg/js/en.js",
"src/assets/blockly/custom_blocks.js"
]
added below lines in my component html file -
<div id="blocklyDiv" style="width: 100%; height: 100%"></div>
<xml id="toolbox" style="display: none">
<category name="Control" colour="120">
<block type="controls_if"></block>
<block type="controls_repeat_ext" disabled="true"></block>
</category>
<category name="Text" colour="230">
<block type="text"></block>
<block type="text_print"></block>
</category>
<category name="Custom" colour="360">
<block type="begin"></block>
<block type="move"></block>
<block type="end"></block>
</category>
</xml>
angular will throw error at this point saying it does not recognise the blockly tags. So need to use NO_ERRORS_SCHEMA in the module or can represent the toolbar XML as a string in the component TS file and use it to inject blockly.
my component TS file -
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ProgramService } from '../services/program.service';
import { IProgram } from '../models/program';
declare var Blockly: any;
@Component({
selector: 'app-program-create',
templateUrl: './program-create.component.html',
styleUrls: ['./program-create.component.scss']
})
export class ProgramCreateComponent implements OnInit {
title: string;
programName: string;
program: IProgram;
workspace: any;
constructor(
private route: ActivatedRoute,
private programService: ProgramService,
private router: Router
) {
this.title = 'Create Visual Program';
this.route.params.subscribe(params => {
this.programName = params['programName'];
this.program = this.programService.getOne(this.programName);
if (!this.program) {
this.program = {
name: this.programName,
xmlData: null
};
}
console.log(
'creating/editing the program - ',
JSON.stringify(this.program)
);
});
}
ngOnInit() {
this.workspace = Blockly.inject('blocklyDiv', {
toolbox: document.getElementById('toolbox'),
scrollbars: false
});
if (this.program.xmlData) {
this.workspace.clear();
Blockly.Xml.domToWorkspace(
Blockly.Xml.textToDom(this.program.xmlData),
this.workspace
);
}
}
saveProgram(): void {
this.program.xmlData = Blockly.Xml.domToText(
Blockly.Xml.workspaceToDom(this.workspace)
);
console.log('saving the program - ', JSON.stringify(this.program));
this.programService.upsertOne(this.program);
this.router.navigate(['listProgram']);
}
}
I have written an article explaining this in details here - Integrate Google Blockly with Angular