ng2-ace-editor icon indicating copy to clipboard operation
ng2-ace-editor copied to clipboard

Any way to use this with Angular's FormBuilder?

Open stephengardner opened this issue 8 years ago • 1 comments

Due to the fact this is a nested component, the standard angular FormBuilder will not hook in properly. That would certainly be a "nice-to-have" feature. If this is already doable I'd love to know how.

stephengardner avatar Dec 18 '17 06:12 stephengardner

It's possible by wrapping the ace-editor into a new component that implements ControlValueAccessor:

import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'tcc-code-editor',
  template: `
    <div ace-editor
         (textChange)="onTextChange($event)"
         (textChanged)="onTextChanged($event)"
         [text]="value"
         [mode]="mode"
         [theme]="theme"
         [readOnly]="readOnly"
         [autoUpdateContent]="autoUpdateContent"
         [durationBeforeCallback]="durationBeforeCallback"
         style="min-height: 200px; width:100%; overflow: auto;">
    </div>
  `,
  styleUrls: ['./code-editor.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => CodeEditorComponent),
    }
  ]
})
export class CodeEditorComponent implements ControlValueAccessor {

  @Input() mode = 'sql';
  @Input() theme = 'clouds';
  @Input() readOnly = false;
  @Input() autoUpdateContent = true;
  @Input() durationBeforeCallback = 1000;

  /**
   * Gets called when the editor's value is about to change
   * @type {EventEmitter<string>} The editor's new value
   */
  @Output() textChange = new EventEmitter<string>();

  /**
   * Gets called when the editor's value has changed
   * @type {EventEmitter<string>} The editor's new value
   */
  @Output() textChanged = new EventEmitter<string>();

  _value: string;

  _changeFn: (_: any) => void;
  _touchedFn: any;


  constructor() { }


  // ControlValueAccessor implementation

  registerOnChange(fn: (_: any) => void): void {
    this._changeFn = fn;
  }

  registerOnTouched(fn: any): void {
    this._touchedFn = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.readOnly = isDisabled;
  }

  writeValue(obj: any): void {
    this.value = obj;
  }


  // Event handling

  onTextChange(text: string) {
    this._value = text;

    if (this._changeFn) {
      this._changeFn(text);
    }

    this.textChange.emit(text);
  }

  onTextChanged(text: string) {
    this._value = text;

    if (this._changeFn) {
      this._changeFn(text);
    }

    this.textChanged.emit(text);
  }


  // Property accessors

  get value(): string {
    return this._value;
  }

  set value(value: string) {
    this.onTextChange(value);
    this._value = value;
    this.onTextChanged(value);
  }

}

This component does not implement custom validation.

leNicDev avatar Jan 31 '18 13:01 leNicDev