formio.js icon indicating copy to clipboard operation
formio.js copied to clipboard

Feature: Enable Autocomplete with Language tools for Ace editor

Open besmiralia opened this issue 5 years ago • 8 comments

I am trying to introduce autocomplete from components when using javascript code in customDefaultValue and calculatedValue. I noticed ace editor has an autocomplete functionality which can be enabled by including the script ext-language_tools.js and activating it with. editor.require('ace/ext/language_tools');

below is the snippet from Component.js >addAce

addAce(element, settings, onChange) {
...
    settings = _.merge(settings, {
      enableBasicAutocompletion: true,
      enableSnippets: true,
      enableLiveAutocompletion: true
    });
    settings = _.merge(this.wysiwygDefault.ace, _.get(this.options, 'editors.ace.settings', {}), settings || {});
    return Formio.requireLibrary('ace', 'ace', _.get(this.options, 'editors.ace.src', ACE_URL), true)
      .then((editor) => {
        editor.require('ace/ext/language_tools');
        editor = aceLib.edit(element);
        editor.removeAllListeners('change');
...

I tried changing the ACE_URL to an array which includes both scripts but it looks like the tools script loads before the main ace script and it throws errors.

I am having some trouble including and activating the script above. If you can guide me on that, I can later make it a pull request to include the new feature.

besmiralia avatar Nov 06 '20 13:11 besmiralia

Try adding this to your own application.

const addAce = Formio.Components.components.component.addAce;
Formio.Components.components.component.addAce = function(element, settings, onChange) {
  return addAce.call(this, element, settings, onChange).then(function(editor) {
    editor.require('ace/ext/language_tools');
    return editor;
  });
};

travist avatar Nov 06 '20 15:11 travist

Thank you @travist I will try this today and let you know

besmiralia avatar Nov 09 '20 15:11 besmiralia

Hi @travist I tested the above in the following fiddle. https://jsfiddle.net/8whur5o0/1/ It seems like addAce from the first line returns undefined

besmiralia avatar Nov 10 '20 18:11 besmiralia

Forgot the prototype

const addAce = Formio.Components.components.component.prototype.addAce;
Formio.Components.components.component.prototype.addAce = function(element, settings, onChange) {
  return addAce.call(this, element, settings, onChange).then(function(editor) {
    editor.require('ace/ext/language_tools');
    return editor;
  });
};

travist avatar Nov 11 '20 15:11 travist

Thank you @travist This seems to be working

https://jsfiddle.net/8whur5o0/3/

besmiralia avatar Nov 11 '20 16:11 besmiralia

Hi @travist This is an updated fiddle https://jsfiddle.net/8whur5o0/5/ with more components in the form and autocomplete pulling data from its components. It still seems to be some timing issue because sometimes it works sometimes it throws the error below which I believe is due to including both scripts (main ace.js + language tools.js) and the second one (language-tools) being resolved first.

ext-language_tools.js:1 Uncaught ReferenceError: define is not defined
    at ext-language_tools.js:1

besmiralia avatar Nov 11 '20 19:11 besmiralia

Try including the ACE editor in the DOM before you load the Form.io renderer. The way our renderer works is it first looks in the global context for a library, in this case it looks for "window.ace" and if that exists, it will NOT lazy load the library. This will ensure that the library is included before Form.io is executed. You may also be able to add your plugins at that moment as well.

travist avatar Nov 12 '20 15:11 travist

Hi @travist This is an updated fiddle https://jsfiddle.net/8whur5o0/5/ with more components in the form and autocomplete pulling data from its components. It still seems to be some timing issue because sometimes it works sometimes it throws the error below which I believe is due to including both scripts (main ace.js + language tools.js) and the second one (language-tools) being resolved first.

ext-language_tools.js:1 Uncaught ReferenceError: define is not defined
    at ext-language_tools.js:1

hello @besmiralia , I'm trying to do the same thing that you were trying to do (but I'm using react). Did you manage to succeed ?

jeanslegel avatar Apr 13 '23 17:04 jeanslegel