Skip to content

Commit

Permalink
feat: formControl support
Browse files Browse the repository at this point in the history
BREAKING CHANGE: use `ngModel` instead of `html` for HTML content binding
  • Loading branch information
sibiraj-s committed Nov 24, 2017
1 parent 3225bcf commit ba350a8
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ <h6>WYSIWYG Editor for Angular Applications.</h6>
</div>

<div class="editor block">
<app-ngx-editor [config]="editorConfig" [placeholder]="'Enter text here...'" [spellcheck]="true" [(html)]="htmlContent"></app-ngx-editor>
<app-ngx-editor [config]="editorConfig" [placeholder]="'Enter text here...'" [spellcheck]="true" [(ngModel)]="htmlContent"></app-ngx-editor>
</div>

<div *ngIf="htmlContent" class="htmlblock block">
Expand Down
4 changes: 3 additions & 1 deletion src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { TestBed, async } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { NgxEditorModule } from './ngx-editor/ngx-editor.module';
import { HttpClientModule } from '@angular/common/http';

describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule, NgxEditorModule],
imports: [FormsModule, HttpClientModule, NgxEditorModule],
declarations: [
AppComponent
],
Expand Down
4 changes: 3 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { NgxEditorModule } from './ngx-editor/ngx-editor.module';
Expand All @@ -12,7 +13,8 @@ import { NgxEditorModule } from './ngx-editor/ngx-editor.module';
imports: [
BrowserModule,
HttpClientModule,
NgxEditorModule
NgxEditorModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
Expand Down
2 changes: 1 addition & 1 deletion src/app/ngx-editor/ngx-editor.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<!-- text area -->
<div class="ngx-editor-textarea" [attr.contenteditable]="config['editable']" [attr.placeholder]="config['placeholder']" (input)="onContentChange($event.target.innerHTML)"
[attr.translate]="config['translate']" [attr.spellcheck]="config['spellcheck']" [style.height]="config['height']" [style.minHeight]="config['minHeight']"
[style.resize]="Utils?.canResize(resizer)" (focus)="onFocus()" (blur)="onBlur($event.target.innerHTML)" #ngxTextArea></div>
[style.resize]="Utils?.canResize(resizer)" (focus)="onFocus()" (blur)="onBlur()" #ngxTextArea></div>

<app-ngx-editor-message></app-ngx-editor-message>

Expand Down
88 changes: 61 additions & 27 deletions src/app/ngx-editor/ngx-editor.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
Component, OnInit, OnChanges, Input,
Output, ViewChild, HostListener, ElementRef, EventEmitter, SimpleChanges
Component, OnInit, Input, Output,
ViewChild, HostListener, ElementRef, EventEmitter,
Renderer2, forwardRef
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

import { CommandExecutorService } from './common/services/command-executor.service';
import { MessageService } from './common/services/message.service';
Expand All @@ -12,10 +14,17 @@ import * as Utils from './common/utils/ngx-editor.utils';
@Component({
selector: 'app-ngx-editor',
templateUrl: './ngx-editor.component.html',
styleUrls: ['./ngx-editor.component.scss']
styleUrls: ['./ngx-editor.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxEditorComponent),
multi: true
}
]
})

export class NgxEditorComponent implements OnInit, OnChanges {
export class NgxEditorComponent implements OnInit, ControlValueAccessor {

@Input() editable: boolean;
@Input() spellcheck: boolean;
Expand All @@ -26,22 +35,23 @@ export class NgxEditorComponent implements OnInit, OnChanges {
@Input() width: string;
@Input() minWidth: string;
@Input() toolbar: any;
@Input() html = '';
@Input() resizer = 'stack';
@Input() config = ngxEditorConfig;

@ViewChild('ngxTextArea') textArea: any;

@Output() htmlChange: EventEmitter<string> = new EventEmitter<string>();

enableToolbar = false;
Utils = Utils;
lastViewModel: any;

private lastViewModel: any = '';
private onChange: (value: string) => void;
private onTouched: () => void;

constructor(
private _elementRef: ElementRef,
private _messageService: MessageService,
private _commandExecutor: CommandExecutorService) { }
private _commandExecutor: CommandExecutorService,
private _renderer: Renderer2) { }

/*
* events
Expand All @@ -56,12 +66,20 @@ export class NgxEditorComponent implements OnInit, OnChanges {
}

onContentChange(html): void {
this.update(html);

if (typeof this.onChange === 'function') {
this.onChange(html);
}

return;
}

onBlur(html): void {
this.update(html);
onBlur(): void {

if (typeof this.onTouched === 'function') {
this.onTouched();
}

return;
}

Expand All @@ -88,15 +106,39 @@ export class NgxEditorComponent implements OnInit, OnChanges {
return;
}

// update view
refreshView(): void {
this.textArea.nativeElement.innerHTML = this.html || '';
return;
/*
* Write a new value to the element.
*/
writeValue(value: any): void {
if (value === undefined) {
return;
}

this.refreshView(value);
}

update(value): void {
this.lastViewModel = value;
this.htmlChange.emit(value);
/*
* Set the function to be called
* when the control receives a change event.
*/
registerOnChange(fn: any): void {
this.onChange = fn;
}

/*
* Set the function to be called
* when the control receives a touch event.
*/
registerOnTouched(fn: any): void {
this.onTouched = fn;
}

/*
* refresh view/HTML of the editor
*/
refreshView(value): void {
const normalizedValue = value == null ? '' : value;
this._renderer.setProperty(this.textArea.nativeElement, 'innerHTML', normalizedValue);
return;
}

Expand All @@ -109,12 +151,4 @@ export class NgxEditorComponent implements OnInit, OnChanges {
this.executeCommand('enableObjectResizing');
}

ngOnChanges(changes: SimpleChanges) {
if (changes.html) {
if (this.lastViewModel !== changes.html.currentValue) {
this.refreshView();
}
}
}

}
10 changes: 4 additions & 6 deletions src/app/ngx-editor/ngx-grippie/ngx-grippie.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ElementRef } from '@angular/core';
import { ElementRef, Renderer2 } from '@angular/core';

import { NgxGrippieComponent } from './ngx-grippie.component';
import { NgxEditorComponent } from '../ngx-editor.component';
import { MessageService } from '../common/services/message.service';
import { CommandExecutorService } from '../common/services/command-executor.service';

export class MockElementRef extends ElementRef {
constructor() { super(null); }
}

describe('NgxGrippieComponent', () => {
let component: NgxGrippieComponent;
let fixture: ComponentFixture<NgxGrippieComponent>;
Expand All @@ -21,7 +17,9 @@ describe('NgxGrippieComponent', () => {
NgxEditorComponent,
MessageService,
CommandExecutorService,
{ provide: ElementRef, useClass: MockElementRef }]
{ provide: ElementRef, useValue: this.elementRef },
{ provide: Renderer2, useValue: this.renderer }
]
})
.compileComponents();
}));
Expand Down

0 comments on commit ba350a8

Please sign in to comment.