Skip to content

Commit

Permalink
Merge pull request #98 from dkrahn/t/97
Browse files Browse the repository at this point in the history
Other: Added example of integration reactive forms with `<ckeditor>` component.
  • Loading branch information
ma2ciek committed May 23, 2019
2 parents f5e63c3 + 170c51c commit 3f19f92
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ <h1>CKEditor integration with Angular 2+</h1>
<ul>
<li><a routerLink="/simple-usage" routerLinkActive="active">Simple usage</a></li>
<li><a routerLink="/forms" routerLinkActive="active">Integration with forms (<code>ngModel</code>)</a></li>
<li><a routerLink="/reactive-forms" routerLinkActive="active">Integration with reactive forms (<code>formControlName</code>)</a></li>
</ul>
</nav>

Expand Down
6 changes: 5 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';

import { CKEditorModule } from '../ckeditor/ckeditor.module';
import { SimpleUsageComponent } from './simple-usage/simple-usage.component';
import { DemoFormComponent } from './demo-form/demo-form.component';
import { DemoReactiveFormComponent } from './demo-reactive-form/demo-reactive-form.component';

const appRoutes: Routes = [
{ path: '', redirectTo: '/simple-usage', pathMatch: 'full' },
{ path: 'simple-usage', component: SimpleUsageComponent },
{ path: 'forms', component: DemoFormComponent },
{ path: 'reactive-forms', component: DemoReactiveFormComponent },
];

@NgModule( {
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
CKEditorModule,
RouterModule.forRoot( appRoutes )
],
declarations: [
AppComponent,
DemoFormComponent,
DemoReactiveFormComponent,
SimpleUsageComponent
],
providers: [],
Expand Down
34 changes: 34 additions & 0 deletions src/app/demo-reactive-form/demo-reactive-form.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
textarea {
font-family: monospace;
}

form {
background: #eee;
padding: 1em 1.5em;
}

form label {
display: block;
font-weight: bold;
}

form input {
width: 30em;
}

form > div {
margin-bottom: 1em;
}

pre {
word-wrap: break-word;
white-space: pre-wrap;
}

p.alert {
color: orange;
}

p.alert::before {
content: "⚠️ ";
}
39 changes: 39 additions & 0 deletions src/app/demo-reactive-form/demo-reactive-form.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<h2>Integration with reactive forms (<code>ngModel</code>)</h2>

<form (ngSubmit)="onSubmit()" [formGroup]="demoReactiveForm">
<h3>User profile form</h3>

<div>
<label for="name">Name</label>
<input formControlName="name" type="text" name="name" id="name">
</div>

<div>
<label for="surname">Surname</label>
<input formControlName="surname" type="text" name="surname" id="surname">
</div>

<label for="description">Description</label>
<ckeditor
formControlName="description"
[editor]="Editor"
id="description"
name="description">
</ckeditor>

<p *ngIf="description && description.dirty" class="alert">Description is "dirty".</p>
<p *ngIf="description && description.touched" class="alert">Description has been "touched".</p>

<p><button type="reset" (click)="reset()">Reset form</button></p>
<p><button type="submit">Submit this form</button> <em>(Open the console first)</em></p>
</form>

<h3>Editor data preview (readable and writable)</h3>
<p>
Note that it's only a prove of concept of using the `ngModel`.
It allows editing, but the editor instantly strips out unknown tags and autoparagraphs text outside of block elements.
</p>
<textarea [(ngModel)]="description.value" style="width: 100%; height: 40px"></textarea>

<h3>Form data preview</h3>
<pre>{{ formDataPreview }}</pre>
63 changes: 63 additions & 0 deletions src/app/demo-reactive-form/demo-reactive-form.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';

import { CKEditorModule } from '../../ckeditor/ckeditor.module';
import { DemoReactiveFormComponent } from './demo-reactive-form.component';
import { By } from '@angular/platform-browser';

describe( 'DemoReactiveFormComponent', () => {
let component: DemoReactiveFormComponent;
let fixture: ComponentFixture<DemoReactiveFormComponent>;

beforeEach( async( () => {
TestBed.configureTestingModule( {
declarations: [ DemoReactiveFormComponent ],
imports: [ CKEditorModule, FormsModule, ReactiveFormsModule ]
} )
.compileComponents();
} ) );

beforeEach( () => {
fixture = TestBed.createComponent( DemoReactiveFormComponent );
component = fixture.componentInstance;
fixture.detectChanges();
} );

afterEach( () => {
fixture.destroy();
} );

it( 'should create', () => {
expect( component ).toBeTruthy();
} );

it( 'should log the model to the console when user submits the form', () => {
const spy = spyOn( console, 'log' );

const submitButton: HTMLButtonElement = fixture.debugElement.query( By.css( 'button[type=submit]' ) ).nativeElement;
submitButton.click();

expect( spy ).toHaveBeenCalledTimes( 1 );
expect( spy.calls.first().args ).toEqual( jasmine.arrayContaining( [
'Form submit, model',
jasmine.objectContaining( {
name: 'John',
surname: 'Doe',
description: '<p>A <b>really</b> nice fellow.</p>'
} )
] ) );
} );

it( 'should reset form after clicking the reset button', ( done: Function ) => {
setTimeout( () => {
const resetButton: HTMLButtonElement = fixture.debugElement.query( By.css( 'button[type=reset]' ) ).nativeElement;
resetButton.click();

fixture.detectChanges();

expect( component.formDataPreview ).toEqual( '{"name":null,"surname":null,"description":""}' );

done();
} );
} );
} );
43 changes: 43 additions & 0 deletions src/app/demo-reactive-form/demo-reactive-form.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
Component,
AfterViewInit
} from '@angular/core';

import * as ClassicEditorBuild from '@ckeditor/ckeditor5-build-classic';
import { FormGroup, FormControl } from '@angular/forms';

@Component( {
selector: 'app-demo-reactive-form',
templateUrl: './demo-reactive-form.component.html',
styleUrls: [ './demo-reactive-form.component.css' ]
} )
export class DemoReactiveFormComponent implements AfterViewInit {
public Editor = ClassicEditorBuild;

public demoReactiveForm = new FormGroup( {
name: new FormControl( 'John' ),
surname: new FormControl( 'Doe' ),
description: new FormControl( '<p>A <b>really</b> nice fellow.</p>' ),
} );

public formDataPreview?: string;

public ngAfterViewInit() {
this.demoReactiveForm!.valueChanges
.subscribe( values => {
this.formDataPreview = JSON.stringify( values );
} );
}

public onSubmit() {
console.log( 'Form submit, model', this.demoReactiveForm.value );
}

public reset() {
this.demoReactiveForm!.reset();
}

public get description() {
return this.demoReactiveForm!.controls.description;
}
}

0 comments on commit 3f19f92

Please sign in to comment.