Integrating Non polymer npm

Hi,

I am trying to integrate Ace Editor and create a component out of it.

Version 14.0.5

@Tag("ace")
@JsModule("https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.6/ace.js")
@JsModule("https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.6/theme-twilight.js")
@NpmPackage(value = "ace-builds", version = "^1.4.6")
public class AceEditor extends Component {

    public void setSize(String size) {
            this.getElement().setProperty("width", size);
            this.getElement().setProperty("height", size);
        }

    public void setTheme() {
        this.getElement().setProperty("theme", "ace/theme/twilight");
    }

    }

In the main view I am calling the above component

        AceEditor aceEditor =new AceEditor();
        aceEditor.setSize("300");
        aceEditor.setTheme();
		add(aceEditor)

The Editor is not getting displayed. Please suggest what am i missing ?

Hi,

You are creating a DOM element called <ace>

@Tag("ace")

You are loading the Ace JS from a CDN

@JsModule("https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.6/ace.js")
@JsModule("https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.6/theme-twilight.js")

You are installing an npm package for Ace into the project

@NpmPackage(value = "ace-builds", version = "^1.4.6")

You are setting a few attributes on the element so you end up with <ace width="300" height="300"></ace>

The most cruicial part that is missing here I think is that you never tell Ace that your element should be used as an Ace editor.

If you look at https://ace.c9.io/#nav=embedding it tells you that you need:

  1. Load ace.js. Check, you have loaded it from CDN. The @NpmPackage annotation serves no purpose if you load Ace from a CDN. You can remove that or you can change the @JsModule annotation to load the file from the npm package, something like @JsModule("ace-builds/src-noconflict/ace.js").
  2. Define a <div> with an id attribute, the one to be used for the editor. This you get by changing @Tag("ace") to @Tag("div") (not strictly necessary) and doing e.g. setId("editor") in the constructor.
  3. Tell Ace about the div that should be made into an editor:
    var editor = ace.edit("editor");
    editor.setTheme("ace/theme/monokai");
    editor.session.setMode("ace/mode/javascript");

This you can do as getElement().executeJs("var editor = ace.edit('editor'); editor.setTheme('ace/theme/monokai');editor.session.setMode('ace/mode/javascript');");

If you do this.getElement().setProperty("theme", "ace/theme/twilight");, then you are setting the property on the DOM element but you should be setting it on the editor object returned by ace.edit it seems.

Finally, the easiest way to allow sizing the component is to implement HasSize which will add setWidth and setHeight and some other variants for you.

Thank you very much Artur. Everything works as you have suggested. The theme and mode works if set at the executeJs but if i set it at the method level its not working.

    public void setFontSize(int size)
    {
        getElement().setProperty("editor.setFontSize",size);
    }

    public void setTheme() {
        getElement().setProperty("editor.setTheme", "ace/theme/tomorrow");
    }

If you want to access to editor object later on you need to store it. I presume it will work if you add something like this.editor = editor to your execJS code. Then the editor object will be stored as a property of the DOM element, which is what you set using getElement().setProperty

Artur Signell:
If you want to access to editor object later on you need to store it. I presume it will work if you add something like this.editor = editor to your execJS code. Then the editor object will be stored as a property of the DOM element, which is what you set using getElement().setProperty

Nice compilation here! Thnx for sharing.