【问题标题】:How do we import Blockly into an Angular 7 application?我们如何将 Blockly 导入 Angular 7 应用程序?
【发布时间】:2019-03-26 01:51:08
【问题描述】:

我正在尝试在 Angular 7 应用程序中使用 Blockly,但我无法注入 Blockly 编辑器。

我已经从https://developers.google.com/blockly/guides/get-started/web 下载了文件并将blockly_compressed.js 复制到我的src 目录中(并将其重命名为blockly.js)。然后我尝试从我的组件访问 Blockly 并得到错误。

我尝试过的:

导入“../blockly.js”

不编译,给出“错误 TS2304:找不到名称 'Blockly'。”

import { Blockly } from '../blockly'

编译,但在浏览器中打开应用时出现以下错误:

ERROR TypeError: _blockly__WEBPACK_IMPORTED_MODULE_4__.Blockly.inject is not a function

添加一个带有以下内容的 blockly.d.ts 文件:

export namespace Blockly {
    export function inject(div: string, config: any): void;
}

给出与上述相同的错误。

还有什么我可以尝试的建议吗?

【问题讨论】:

    标签: angular blockly angular7


    【解决方案1】:

    我能够使用下面提到的配置进行设置 -

    使用 npm 安装块 -

    npm install git://github.com/google/blockly.git#1.20190419.0
    

    在 angular.json 文件的脚本部分中包含以下文件 -

        "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"
        ]
    

    在我的组件 html 文件中添加以下行 -

      <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 此时会抛出错误,说它无法识别块状标签。所以需要在模块中使用NO_ERRORS_SCHEMA或者可以在组件TS文件中将工具栏XML表示为字符串,并使用它来进行块式注入。

    我的组件 TS 文件 -

    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']);
      }
    }
    

    我在这里写了一篇文章详细解释了这一点 - Integrate Google Blockly with Angular

    【讨论】:

      【解决方案2】:

      我的回答没有将 XML 放入模板本身,而是放入一个变量中,该变量可以在模块中没有 NO_ERRORS_SCHEMA 导入的情况下实现集成。

      第 1 步: 从 Blockly 网站下载文件,然后查找:

      • blockly_compressed.js
      • blocks_compressed.js
      • zh.js (或任何你希望你的 blockly 使用的语言)

        将它们复制并粘贴到 src/assets/blockly 中。

      第 2 步:在 angular.json 文件中,添加以下内容(在 projects.architect.build.options 中):

      "scripts": [
                "src/assets/blockly/blockly_compressed.js",
                "src/assets/blockly/blocks_compressed.js",
                "src/assets/blockly/en.js"
      ]
      

      第 3 步: 在您的 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 });
        }
      }
      

      就是这样!

      【讨论】:

        【解决方案3】:

        我假设你正在使用 @angular/cli。

        Demo

        第 1 步:分块安装

        npm install blockly
        

        第二步:在架构节点下的angular.json添加脚本:

        "scripts": [
           "node_modules/blockly/blockly_compressed.js",
           "node_modules/blockly/blocks_compressed.js",
           "node_modules/blockly/msg/js/en.js"
        ]
        

        第 3 步:将NO_ERRORS_SCHEMA 添加到您的 AppModule(这样您就可以在组件中定义自定义标签)

        @NgModule({
          imports:      [ BrowserModule, AppRoutingModule ],
          declarations: [ AppComponent ],
          bootstrap:    [ AppComponent ],
          exports: [AppComponent],
          schemas: [NO_ERRORS_SCHEMA]
        })
        export class AppModule {
        }
        

        第四步:创建一个组件,将Blockly声明为any,并实现AfterViewInit,这样就可以访问DOM中与blockly相关的元素了:

        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 });
          }
        }
        

        注意:NPM 中的 Blockly 包是 v1.0,而最新版本是 v1.2。要使用最新版本,只需下载库,将其放在已知目录中,然后修复您的脚本引用(第 2 步)。

        【讨论】:

        • 在修改 app.module.ts 时,我必须从 @angular/core 导入 NO_ERRORS_SCHEMA 以消除编译错误。
        • 尝试了所有步骤,但仍然无法正常工作:在 ngAfterViewInit() 中获取 ReferenceError: Blockly is not defined
        • 感谢您查看此内容。由于某种原因,该演示根本无法在我的 PC 上运行(我尝试了三种不同的浏览器)。我会在另一台机器上再试一次,以防我的机器出现问题。
        • 是的,我认为 Stackblitz 在处理全局变量时表现不同。如果您在本地尝试应该可以工作
        • 演示不工作无法读取未定义的属性“注入”。看起来不像是特定于机器的东西。
        【解决方案4】:

        使用 ngx-blockly 代替 blockly ,ngx-blockly 是 blockly 的角端口。

        按照 npm 页面中说明的步骤进行操作

        npm install ngx-blockly --save
        

        https://www.npmjs.com/package/ngx-blockly

        【讨论】:

          【解决方案5】:

          你应该先把它添加到angular.json。 所以 Angular CLI 可以构建它。

                  "scripts": [
                    "../blockly.js"
                  ]
          

          【讨论】:

            猜你喜欢
            • 2020-12-14
            • 2016-09-25
            • 1970-01-01
            • 2017-12-28
            • 2018-08-03
            • 2018-02-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多