添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I try to use this addon: https://codemirror.net/demo/loadmode.html

The idea is to put all folder languages in my assets dir, and give formatted url etc ...

How can i access to this variable https://github.com/codemirror/CodeMirror/blob/29e338b8c1f27ade4502839877df7afd49584479/demo/loadmode.html#L65 with ngx-codemirror ?

Another problem: CodeMirror.autoLoadMode(instance, mode) must be called but this.codeMirror.codeMirror.autoLoadMode is not a function

After reading code of loadmode.js: https://github.com/codemirror/CodeMirror/blob/29e338b8c1f27ade4502839877df7afd49584479/addon/mode/loadmode.js#L58

The function seems to not be declared properly on codeMirror instance

its imported down further, those are just @types being imported at the top
https://github.com/TypeCtrl/ngx-codemirror/blob/d5cafceb528b8b95643bd0fa3a7ff858a5c63582/src/lib/codemirror.component.ts#L98

You might make sure you've included your plugin correctly from the first step of use https://github.com/TypeCtrl/ngx-codemirror#use or make sure the codemirror instance has been created when your code runs

console.log(this.codeMirror.codeMirror) , instance is ok. Viewer is ok, but when addons are loaded, no functions are inherited

Same problem with the meta mod:

Just for information, I use angular 6

After a lot of debugging, it seems require creates a scoped instance of CodeMirror.
Addons have to find a global instance of CodeMirror in plain mode to correctly work.
fromTextArea doesn't return all CodeMirror object (this is why i did not find the addons functions).

My final solution is to mix global instance and this component.
For this i need to declare in angular.json all the scripts to import:

"scripts": [
              "node_modules/codemirror/lib/codemirror.js",
              "node_modules/codemirror/mode/meta.js",
              "node_modules/codemirror/addon/mode/loadmode.js"

If we use fromTextArea from scoped instance, the setOption function will not work.
In ngx-codemirror component replace:

declare var require: any; // remove this
const { fromTextArea } = require('codemirror');
this.codeMirror = fromTextArea(this.ref.nativeElement, this._options);
declare var CodeMirror: any; // replaced by "var require..."
this.codeMirror = CodeMirror.fromTextArea(this.ref.nativeElement, this._options);

In my internal component i use declare var CodeMirror: any to access all functions (ref is the childView of ngx-codemirror component)

ngAfterViewInit() {
        CodeMirror.modeURL = this.modeUrl
        const mode = CodeMirror.findModeByFileName(this.file.name).mode // this function is loaded by meta addon
        CodeMirror.autoLoadMode(this.ref.codeMirror, mode) // this function is loaded by loadmode addon
        this.ref.codeMirror.setOption('mode', mode)
          

Importing addons like modes as described in the README works perfectly. Here's my main.ts file:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
// Import your required language in main.ts or at the root of your application
// see https://codemirror.net/mode/index.html
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/css/css';
import 'codemirror/mode/htmlmixed/htmlmixed';
import 'codemirror/addon/edit/matchbrackets';
import 'codemirror/addon/edit/closetag';
import 'codemirror/addon/selection/active-line';
if (environment.production) {
  enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

and here's my options object to enable the above addons:

editorOptions = {
  lineNumbers: true,
  autoCloseTags: true,
  styleActiveLine: true,
  theme: 'monokai',
  mode: 'text/html',
  // define Emmet output profile
  profile: 'xhtml'

Btw, thank you a lot @scttcper for this awesome ngx wrapper for codemirror! 🙌
Cheers!

@scttcper This is what i do for the time being.
But if you replace the 2 lines of code, it should work for everyone:

declare var CodeMirror: any; // replaced by "var require..."
this.codeMirror = CodeMirror.fromTextArea(this.ref.nativeElement, this._options);

If people want to use other addons like me, they will only have to load the libraries via the Angular scripts tag above, for others it will work the same way.

I am attempting to do something similar except in my case is to dynamically define the mode and load it on the fly based on a matrix of user provided data... @johaven could you provide a StackBlitz showing what you did to get loadmode functional? because I am hitting a brick wall trying to deduce this thread.

"scripts": [
              "node_modules/codemirror/lib/codemirror.js",
              "node_modules/codemirror/mode/meta.js",
              "node_modules/codemirror/addon/mode/loadmode.js",
              "node_modules/codemirror/addon/mode/overlay.js"

codemirror.component.ts diff I declare this modified component in my module.

Usage example

import {AfterViewInit, Component, Input, OnInit, ViewChild, ViewEncapsulation} from '@angular/core'
import {HttpClient} from '@angular/common/http'
declare var CodeMirror: any
@Component({
    selector: 'app-files-viewer-text',
    encapsulation: ViewEncapsulation.None,
    styles: [`
      .CodeMirror {
        height: 100%
    `],
    template: `
      <div [style.height.px]="currentHeight">
        <ngx-codemirror #CodeMirror [(ngModel)]="content" [options]=options></ngx-codemirror>
      </div>`
export class FilesViewerTextComponent implements OnInit, AfterViewInit {
    @ViewChild('CodeMirror') ref: any
    @Input() currentHeight: number
    @Input() file: any
    @Input() fileUrl: string
    private readonly modeUrl = '/static/assets/codemirror/mode/%N/%N.js'
    public content: string
    public options: any = {lineNumbers: true, readOnly: true, theme: 'material', mode: 'null'}
    private mode: string = null
    constructor(private http: HttpClient) {
        CodeMirror.modeURL = this.modeUrl
    ngOnInit() {
        const detectedMode = CodeMirror.findModeByFileName(this.file.name)
        if (detectedMode) {
            this.mode = detectedMode.mode
            this.http.get(this.fileUrl, {responseType: 'text'}).subscribe((data: string) => this.content = data)
        } else {
            this.content = 'This file contains binary data that can not be read'
    ngAfterViewInit() {
        if (this.mode) {
            CodeMirror.autoLoadMode(this.ref.codeMirror, this.mode)
            this.ref.codeMirror.setOption('mode', this.mode)