【问题标题】:Integrating CodeMirror with Angular2 (typescript)将 CodeMirror 与 Angular2 集成(打字稿)
【发布时间】:2016-09-02 16:38:52
【问题描述】:

我目前正在将 CodeMirror 编辑器添加到项目中,更准确地说是 Angular2 项目。但我很难做到这一点。我的编辑器的实例化似乎无法正常工作。我的代码如下:

editor.component.ts

import {Component} from 'angular2/core'
import {BrowserDomAdapter} from 'angular2/platform/browser'

declare var CodeMirror: any;

@Component({
    selector: 'editor',
    templateUrl: './meang2app/partials/editor.html'
})

export class Editor{
    dom: BrowserDomAdapter;
    editor: any;
    constructor(){
        this.dom = new BrowserDomAdapter();
        this.editor = new CodeMirror.fromTextArea(this.dom.query("textarea"), {lineNumbers: true, mode: {name: "javascript", globalVars: true}});
    }
}

editor.html

<textarea id="code" name="code">
    <!-- Where a CodeMirror instance should be rendered -->
</textarea>

在我的 index.html 文件中,我执行以下操作:

<html>
<head>

    <title>Angular 2</title>

    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
    <script src="node_modules/angular2/bundles/http.dev.js"></script>
    <script src="node_modules/angular2/bundles/router.dev.js"></script>
    <script src="codemirror/lib/codemirror.js"></script>
    <script src="codemirror/addon/hint/show-hint.js"></script>
    <script src="codemirror/addon/hint/javascript-hint.js"></script>
    <script src="codemirror/mode/javascript/javascript.js"></script>

    <script>
        System.config({
            packages: {        
                app: {
                    format: 'register',
                    defaultExtension: 'js'
                }
            }
        });
        System.import('app/dist/boot')
            .then(null, console.error.bind(console));
    </script>

</head>

<body>
        <app>Loading</app>
</body>

</html>

我正在以这种方式引导我的应用程序,但我不认为这就是问题所在。

boot.ts

import {bootstrap} from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent);

当我尝试运行应用程序时,firefox 告诉我 'EXCEPTION: Error during instantiation of Editor!。',以及 'ORIGINAL EXCEPTION: TypeError: textarea is null' 也是如此。关于发生了什么以及如何解决这个问题的任何想法?

感激不尽

【问题讨论】:

    标签: typescript angular codemirror


    【解决方案1】:

    非常感谢您的帮助,我遵循了您链接中给出的一些提示,并使用指令实现了它。在那之后我也遇到了一些问题,但没什么大不了的:我只是不知道通过组件加载链接标签是不可能的。如果您正在阅读本文并遇到类似问题,这是我的解决方案:

    editor.component.ts

    import {Component, ElementRef} from 'angular2/core'
    import {EditorDirective} from './editor.directive'
    
    @Component({
        selector: 'editor',
        template: `
        <textarea editor id="code" name="code">
            // Some content
        </textarea>
    `,
        directives: [EditorDirective]
    })
    
    
    export class EditorComponent{
        constructor(){}
    }
    

    editor.directive.ts

    import {Directive, ElementRef, Renderer} from 'angular2/core'
    
    declare var CodeMirror: any;
    
    @Directive({
        selector: '[editor]'
    })
    
    export class EditorDirective {
        editor: any;
        constructor(public element: ElementRef, public renderer: Renderer){
            this.editor = new CodeMirror.fromTextArea(element.nativeElement, {lineNumbers: true, mode: {name: "javascript", globalVars: true}});
        }
    }
    

    最后,index.html

    <html>
        <head>
    
        <title>Angular 2 and CodeMirror</title>
    
        <script src="node_modules/es6-shim/es6-shim.min.js"></script>
        <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    
        <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
        <script src="node_modules/systemjs/dist/system.src.js"></script>
        <script src="node_modules/rxjs/bundles/Rx.js"></script>
        <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
        <script src="node_modules/angular2/bundles/http.dev.js"></script>
        <script src="node_modules/angular2/bundles/router.dev.js"></script>
        <script src="codemirror-5.14.2/lib/codemirror.js"></script>
        <script src="codemirror-5.14.2/addon/hint/show-hint.js"></script>
        <script src="codemirror-5.14.2/addon/hint/javascript-hint.js"></script>
        <script src="codemirror-5.14.2/mode/javascript/javascript.js"></script>
        <script src="codemirror-5.14.2/mode/markdown/markdown.js"></script>
    
        <link rel=stylesheet href="codemirror-5.14.2/doc/docs.css">
        <link rel="stylesheet" href="codemirror-5.14.2/lib/codemirror.css">
        <link rel="stylesheet" href="codemirror-5.14.2/addon/hint/show-hint.css">
    
        <script>
            System.config({
                packages: {        
                    meang2app: {
                    format: 'register',
                    defaultExtension: 'js'
                    }
                }
            });
          System.import('meang2app/dist/editor.component')
              .then(null, console.error.bind(console));
        </script>
    
        </head>
    
      <body>
          <app>Loading</app>
      </body>
    
    </html>
    

    【讨论】:

    【解决方案2】:

    根据angular 2 documentation,您应该避免使用 ElementRef。特别是,您应该避免:

    您的应用程序和渲染层之间的紧密耦合将导致无法将两者分开并将您的应用程序部署到 Web Worker 中。

    改用Renderer2

    editor.directive.ts

    @Directive({
      selector: '[editor]'
    })
    export default class EditorDirective {
      editor: any;
    
      constructor(private _renderer: Renderer) {}
    
      ngAfterViewInit() {
        this.editor = CodeMirror.fromTextArea(
          this._renderer.selectRootElement('[editor]'),
          {
            lineNumbers: true, 
            mode: {name: "javascript", globalVars: true}
          }
        );
      }
    }
    

    【讨论】:

      【解决方案3】:

      问题可能是您没有通过 BrowserDomAdapter 获取正确的 DOM 元素(我猜它会从 html 根目录而不是从当前组件上下文中查找 textarea,这是它不知道的)和因此文本框变为空。

      这里有一些方法描述了如何在模板中获取对元素的引用并在组件代码中使用它(例如,为了实例化 codemirror):Angular2: What is the best way to get a reference of a template element

      【讨论】:

        【解决方案4】:

        codemirror 上有一个 Angular 包装器 - ngx-codemirror - https://github.com/scttcper/ngx-codemirror

        【讨论】:

          猜你喜欢
          • 2023-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多