roroettg / ngx-blockly

An angular wrapper around google's blockly library
Apache License 2.0
43 stars 23 forks source link

appendFromXml not working. #31

Closed vunter closed 3 years ago

vunter commented 3 years ago

i'm trying to append any block from previously defined xml, like:

But nothing happen, it just doesn't work at all. Before that, i'm using "fromXml" (which clear the previous content, something that i don't want to do when i call appendFromXml). fromXml works, just with an error at the console: ERROR TypeError: Cannot read property 'setResizesEnabled' of undefined at Object.Blockly.Xml.clearWorkspaceAndLoadFromXml (blockly_compressed.js:181) at NgxBlocklyComponent.fromXml (ngx-blockly.js:398).

Thats my code where i try to append a block that comes from database at the workspace: let saved = localStorage.getItem('saved_workspace'); if (saved) this.workspace.fromXml(saved); this.workspace.appendFromXml(this.globals.xml);

roroettg commented 3 years ago

Hi,

thank you for reporting this bug.

I was able to reproduce it and just released a fix for it. Please check if it is fixed with version 10.0.8.

vunter commented 3 years ago

Hi, thanks for the quick response, but i still can't use the append method, now i get the error:

Uncaught TypeError: Cannot convert undefined or null to object at hasOwnProperty () at Object.Blockly.Xml.appendDomToWorkspace (blockly_compressed.js:185) at NgxBlocklyComponent.appendFromXml (ngx-blockly.js:393) at eval (eval at (main.js:1), :1:16)

I'm calling it this way (i'm from Brazil, so some texts will be in portuguese): this.blocoService.getBlocosByProfessor(3).toPromise().then((r) => { this.workspace.fromXml(r[0].conteudo); this.workspace.appendFromXml(r[1].conteudo); }) The "fromXml" method still working, only throwing the 'setResizesEnabled' error that i already mentioned before.

In my package.json: "ngx-blockly": "^10.0.8"

roroettg commented 3 years ago

Could you provide the complete component or when in the life-cycle you are calling this?

It seems like you trying to add/append to the workspace before it its completely initialized.

vunter commented 3 years ago

I'm using it inside the "AfterViewInit", the only way i could make "fromXml" work properly. After i use "fromXml", workspace should be completely initialized, right? And "appendFromXml" is called right after the "fromXml", here's my component:


import { ToastService } from './../../../toast.service';
import { Aula } from './../../../shared/entity/Aula';
import { AulaService } from './../../../shared/services/aula.service';
import { BlocosService } from './../../../shared/services/blocos.service';
import { Global } from './../../../shared/Global';
import { COLOUR_CATEGORY, FUNCTIONS_CATEGORY, LISTS_CATEGORY, LOGIC_CATEGORY, LOOP_CATEGORY, MATH_CATEGORY, NgxBlocklyComponent, NgxBlocklyConfig, NgxBlocklyGeneratorConfig, NgxToolboxBuilderService, TEXT_CATEGORY, VARIABLES_CATEGORY } from 'ngx-blockly';
import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
  selector: 'app-aula-aluno',
  templateUrl: './aula-aluno.component.html',
  styleUrls: ['./aula-aluno.component.css']
})
export class AulaAlunoComponent implements OnInit, AfterViewInit {

  @ViewChild(NgxBlocklyComponent) workspace;
  conteudo: string;
  idAula: number;
  maxBlocks: number = 10;
  leftBlocks: string = '';
  aula: Aula;

  public config: NgxBlocklyConfig = {
    scrollbars: true,
    trashcan: true,
    collapse: true,
    search: {
      enabled: true,
      placeholder: 'Pesquise'
    },
    zoom: {
      controls: true,
      wheel: true,
      startScale: 1.0,
      maxScale: 10.0,
      minScale: 0.3,
      scaleSpeed: 1.2
    }

  };

  public generatorConfig: NgxBlocklyGeneratorConfig = {
    javascript: true
  };

  constructor(
    private toast: ToastService,
    private ngxToolboxBuilder: NgxToolboxBuilderService,
    private route: ActivatedRoute,
    private globals: Global,
    private blocoService: BlocosService,
    private aulaService: AulaService
  ) {

    this.route.queryParams.subscribe(params => { this.idAula = params['id'] })
    this.aulaService.getAula(this.idAula).toPromise().then(
      (response) => {
        this.aula = response;
        this.config.maxBlocks = this.aula.quantidadeMaxBlocos;
      }, (errorResponse) => {
        errorResponse.error.erros.forEach((e) => {
          toast.showError(e)
        })
      });

    LOGIC_CATEGORY.name = 'Lógica';
    LOOP_CATEGORY.name = 'Loops';
    MATH_CATEGORY.name = 'Matemática';
    TEXT_CATEGORY.name = 'Textos';
    LISTS_CATEGORY.name = 'Listas';
    COLOUR_CATEGORY.name = 'Cores';
    VARIABLES_CATEGORY.name = 'Variáveis';
    FUNCTIONS_CATEGORY.name = 'Funções';

    ngxToolboxBuilder.nodes = [
      LOGIC_CATEGORY,
      LOOP_CATEGORY,
      MATH_CATEGORY,
      TEXT_CATEGORY,
      LISTS_CATEGORY,
      COLOUR_CATEGORY,
      VARIABLES_CATEGORY,
      FUNCTIONS_CATEGORY
    ];

    this.config.toolbox = ngxToolboxBuilder.build();
  }

  ngOnInit(): void {
  }

  ngAfterViewInit() {
    let saved_id = localStorage.getItem('saved_id');
    if (saved_id && this.idAula) {
      if (Number.parseInt(saved_id) == this.idAula) {
        let saved = localStorage.getItem('saved_workspace');
        if (saved)
          this.workspace.fromXml(saved);
      }
    } else {
      this.blocoService.getBlocosByProfessor(3).toPromise().then((r) => {
        this.workspace.fromXml(r[0].conteudo);
        this.workspace.appendFromXml(r[1].conteudo);
      })
    }
  }

  onCode(code: string) {
    if (code) {
      this.conteudo = code;
      localStorage.setItem('saved_workspace', this.workspace.toXml());
      localStorage.setItem('saved_id', this.idAula.toString());
    } else {
      localStorage.removeItem('saved_id');
      localStorage.removeItem('saved_workspace');
    }
    this.leftBlocks = this.workspace.workspace.remainingCapacity();

  }

  getCode(): string {
    return this.conteudo;
  }

}
roroettg commented 3 years ago

Since we inject the workspace at AfterViewInit, we kind of have race condition here and you try to add to the workspace before it is initialized. As a workaround I would suggest, that encapsulate your import/append like this.

setTimeout(() => {
        this.workspace.fromXml(r[0].conteudo);
        this.workspace.appendFromXml(r[1].conteudo);
});
vunter commented 3 years ago

Ok, it works now :D Thank you so much, i will close this issue, but when you can, take a look at this error when using the list category, it is thrown at the console:

Uncaught ReferenceError: goog is not defined at lists.js:18

At first look, it don't bring any problem to the app or the use of blocks.

thank you so much <3