antonyboom
antonyboom

Reputation: 1181

angular 5 and quilljs [Parchment] Unable to create blot

I'm working with primeng editor and there is no any problem with editor itself, however I'm fighting two days in a row with extending standard block for custom tag, official documentation says for any additional feature to use quilljs api

I've checked every api and issue on github and it seems to me, I'm on the right way, but I can't rid off this annoying error:

ERROR Error: [Parchment] Unable to create marker blot
at new ParchmentError (scripts.bundle.js:148)
at Object.create (scripts.bundle.js:178)
at BlockBlot.insertAt (scripts.bundle.js:7323)
at Block.insertAt (scripts.bundle.js:855)
at Scroll.ContainerBlot.insertAt (scripts.bundle.js:3404)
at ScrollBlot.insertAt (scripts.bundle.js:7060)
at Scroll.insertAt (scripts.bundle.js:4252)
at Editor.insertEmbed (scripts.bundle.js:2606)
at scripts.bundle.js:1379
at Quill.modify (scripts.bundle.js:1610)

What I'm trying to achieve is to add custom tag with non editable content inside. Here is my code:

...
import {Editor} from 'primeng/editor';

import * as Quill from 'quill';
import * as Parchment from 'parchment';
const Block = Quill.import('blots/block/embed');
class BlockEmbed extends Parchment.default.Embed {}
BlockEmbed.prototype = Block.prototype;

export class Variable extends BlockEmbed {

  static blotName = 'marker';
  static tagName = 'marker';

  static create(value: any) {
    console.log(value);
    const node = (super.create(value) as any);
    node.innerHTML = '<span contenteditable=false>' + value + '</span>';
    node.setAttribute('contenteditable', false);
    return node;
  }

}

Variable.blotName = 'marker';
Variable.tagName = 'marker';

Quill.register('formats/marker', Variable);

@Component({
  selector: 'manager',
  templateUrl: './manager.component.html',
  styleUrls: ['./manager.component.css']
})

export class ManagerComponent implements OnInit, AfterViewInit {

   private quill: any;
  @ViewChild(Editor) editorComponent: Editor;

  ngOnInit() {}

 // based on primeng github issue this how we can get references to quill 
  ngAfterViewInit() {
    this.quill = this.editorComponent.quill;
  }

 variableSelected(event) {
    // grubbing string variable from event 
    this.quill.insertEmbed(this.cursor.index || 0, 'marker', event.value);
  }

}

Based on these topics from quill github, my code should work fine:

topic 1

topic 2

topic 3

topic 4

So could somebody help me to find what I'm missing or where my problem is? Thanks in advance.

Upvotes: 6

Views: 8030

Answers (3)

Oleksii Zubko
Oleksii Zubko

Reputation: 21

Works fine for me in that way:

import * as QuillNamespace from 'quill';
const Quill: any = QuillNamespace;

const BlockEmbed = Quill.import('blots/block/embed');

Upvotes: 2

antonyboom
antonyboom

Reputation: 1181

I was apple to fix my problem with next approach

...
declare var Quill: any;
const BlockEmbed = Quill.import('blots/embed');

export class Variable extends BlockEmbed {

  static create(value: any) {
    const node = super.create(typeof value === 'object' ? value.text : value);
    node.innerText = typeof value === 'object' ? value.text : value;
    node.setAttribute('contenteditable', false);
    return node;
  }

  static value(node) {
    return {
      style: node.getAttribute('contenteditable'),
      text: node.innerText
    };
  }

}

Variable['blotName'] = 'marker';
Variable['className'] = 'marker';
Variable['tagName'] = 'span';

Quill.register('formats/marker', Variable);

export class ManagerComponent implements OnInit, AfterViewInit {

  private quill: any;

  @ViewChild('stepper') stepper;
  @ViewChild(Editor) editorComponent: Editor;

...

variableSelected(event) {
    this.quill.insertEmbed(this.cursor.index || 0, 'marker', event.value, 'user');
    this.quill.update('user'); 
  }

Upvotes: 11

Damien CFS
Damien CFS

Reputation: 1

I am having the same issue using ngx-quill. I believe the problem is related to the fact that the component is declared in a scope hidden by webpack. Therefore we do not have access to the right Quill instance to register the extra components. I got a solution thanks to the help of KillerCodeMonkey at https://github.com/KillerCodeMonkey/ngx-quill. Remove any other quill.js import (in package.json or .angular-cli.json) and this should work on angular/core 5.2.0:

import * as Quill from 'quill'; 
import Parchment from "parchment";

console.log(Quill);
const QuillBlockEmbed = (Quill as any).import('blots/block/embed');

class BlockEmbed extends Parchment.Embed {};
BlockEmbed.prototype = QuillBlockEmbed.prototype;

class MyBlot extends BlockEmbed {
    static create(value) {
        let node: Element = super.create(value) as Element;
        if (typeof value === 'object') {
            node.classList.add("my-class");
        }
        return node;
    }
...
}

MyBlot.blotName = 'boltTwo';
MyBlot.tagName = 'img';

(Quill as any).register({ 'blots/myblot':MyBlot});

Upvotes: 0

Related Questions