Integrate the ng2-ace library into the newly created angular-cli (angular2) project using SystemJS

I just created an angular2 project with the latest angular-cli . Now I want the ace editor to work and work using the ng2-ace library. I want to do this in its purest form, using SystemJS as the module loader.

I did

npm install --save ng2-ace 

then I added the following lines in angular-cli-builds.js to the vendorNpmFiles array

 'ng2-ace/index.js', 'brace/**/*.js 

then I added the following to system-config.ts

  const map: any = { 'ng2-ace': 'vendor/ng2-ace', 'brace': 'vendor/brace' }; /** User packages configuration. */ const packages: any = { 'brace': { format: 'cjs', defaultExtension: 'js', main: 'index.js' }, 'ng2-ace': { format: 'cjs', defaultExtension: 'js', main: 'index.js' } }; 

Now I tried to import the directive from the component

 import { AceEditorDirective } from 'ng2-ace'; 

This causes the ng serve compiler to be canceled with the following error:

 The Broccoli Plugin: [BroccoliTypeScriptCompiler] failed with: Error: Typescript found the following errors: Cannot find module 'ng2-ace'. 

I tried to execute the Readme from angular-cli and got the google material design library. However, I do not know what I'm doing wrong trying to load the ng2-ace library.

+5
source share
1 answer

I think the reason this is so complicated is because there is no typed library there. I was able to get an approximate equivalent of this work by adding a few things. My version has a rather old configuration, but you can improve it.

system-config needs this:

 const map:any = { 'brace': 'vendor/brace', 'w3c-blob': 'vendor/w3c-blob', 'buffer': 'vendor/buffer-shims' }; 

may also be required:

 const packages:any = { 'w3c-blob': { format: 'cjs', defaultExtension: 'js', main: 'index.js' }, 'brace': { format: 'cjs', defaultExtension: 'js', main: 'index.js' }, 'buffer': { format: 'cjs', defaultExtension: 'js', main: 'index.js' } }; 

Then you also need to add these things as npm dependencies in angular-cli-build.js:

 module.exports = function(defaults) { return new Angular2App(defaults, { vendorNpmFiles: [ /* your stuff goes here, then add: */ 'brace/**/*.js', 'w3c-blob/index.js', 'buffer-shims/index.js' ] }); 

To a large extent, you get everything you need, depending on the dependencies. At the moment, I have added my own directive. The important parts are here:

 import { Directive, ElementRef, EventEmitter } from '@angular/core'; 

Now import the brackets and all the modes and themes that you will use:

 import 'brace'; declare let ace; import 'vendor/brace/mode/javascript'; import 'vendor/brace/theme/monokai'; 

"declare let ace" allows you to access brackets even if there are no typings, and this is not a true typescript module.

I called my js-editor directive, and you attach it to a tag of the appropriate height and width. Documents for brackets are said to apply the "block" style to a div. Then declare the directive:

 @Directive({ selector: '[js-editor]', inputs: ['text'], outputs: ['textChanged', 'editorRef'] }) export class JsEditor { editor : any; textChanged : EventEmitter<any>; editorRef : EventEmitter<any>; value : string; set text(value) { // if(value === this.oldVal) return; // this.editor.setValue(value); // this.editor.clearSelection(); this.editor.focus(); } constructor(elementRef : ElementRef) { this.textChanged = new EventEmitter(); this.editorRef = new EventEmitter(); const el = elementRef.nativeElement; el.classList.add('editor'); 

Setting the base path is a key element in finding modes and themes. This is really the wrong place to install it - it needs to be done globally, and ONLY ONCE ... but it was just an experiment to see if it would work, so I did it here:

  ace.config.set('basePath', 'vendor/brace'); 

Finally, create an editor:

  this.editor = ace.edit(el); 

and then set your mode and theme. Note that these LOOK modes / themes are similar along the way, but in reality this is not the case. The ace (or maybe Brace) will use these lines to generate the path using basePath above:

  this.editor.getSession().setMode('ace/mode/javascript'); this.editor.setTheme('ace/theme/monokai'); setTimeout(() => { this.editorRef.next(this.editor); }); this.editor.on('change', () => { /* do whatever you want here */ }); } } 

This is a general idea. It really needs to be wrapped in a nice custom directive along the ng2-ace lines, but I'm not the guy who did it, I just wanted you to head in the right direction.

- Chris

+2
source

All Articles