Skip to content

Commit

Permalink
INT-2974: Support OnPush change detection (#368)
Browse files Browse the repository at this point in the history
* INT-2974: Now uses OnPush change detection

* INT-2974: Added a story to show support for OnPush change detection form/parent element

* INT-2974: Added changelog entry

* INT-2974: Update CHANGELOG.md

Co-authored-by: Andrew Herron <[email protected]>

---------

Co-authored-by: Andrew Herron <[email protected]>
  • Loading branch information
danoaky-tiny and TheSpyder authored Apr 5, 2024
1 parent b34b909 commit 76e0e52
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Usage of RxJS deprecated operators. #INT-3274
### Added
- Support for Angular 15, 16 & 17. #INT-3274
- Support for the OnPush change detection strategy. #INT-2974
### Improved
- Updated Storybook to v8, as well as now using CSFv3 components. #INT-3274

Expand Down
12 changes: 12 additions & 0 deletions stories/Editor.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { EventBindingComponent } from './event-binding/EventBinding.component';
import { EventForwardingComponent } from './event-forwarding/EventForwarding.component';
import { FormControlComponent } from './form-control/FormControl.component';
import { FormWithOnPushComponent } from './form-with-on-push/form-with-on-push.component';
import { BlogComponent } from './formvalidation/FormValidation.component';
import { DisablingComponent } from './disable/Disable.component';
import { ViewQueryComponent } from './viewquery/Viewquery.component';
Expand Down Expand Up @@ -97,6 +98,17 @@ export const FormControlStory: StoryObj<EditorComponent> = {
}
};

export const FormStateStory: StoryObj<EditorComponent> = {
name: 'Form with on-push change detection',
render: () => ({
moduleMetadata: {
imports: [ ReactiveFormsModule, FormsModule ],
declarations: [ FormWithOnPushComponent ],
},
template: `<form-with-on-push apiKey="${apiKey}"/>`
}),
};

export const FormValidationStory: StoryObj<EditorComponent> = {
name: 'Form Validation',
render: () => ({
Expand Down
31 changes: 31 additions & 0 deletions stories/form-with-on-push/form-with-on-push.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-parameter-properties */
import {
Component,
ChangeDetectionStrategy,
Input,
} from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import type { EditorComponent } from '../../tinymce-angular-component/src/main/ts/public_api';

@Component({
selector: 'form-with-on-push',
templateUrl: './form-with-on-push.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FormWithOnPushComponent {
@Input() public apiKey = '';
public readonly initialValue = '';
public readonly init: EditorComponent['init'] = {
plugins: [ 'help' ],
};
public readonly form = new FormGroup({
tiny: new FormControl('', {
validators: Validators.compose([
Validators.required,
Validators.minLength(10)
]),
}),
regular: new FormControl(''),
});
}
24 changes: 24 additions & 0 deletions stories/form-with-on-push/form-with-on-push.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<form [formGroup]="form" style="display: flex; gap: 0.2em; flex-direction: column;">
<editor
formControlName="tiny"
plugins="table"
init="{ width: '200px', }"
/>
<br />
<label>
<span>Regular input</span>
<br />
<input type="text" formControlName="regular" />
</label>
<br />
<button type="reset" style="width: 200px">Reset form</button>
<button [disabled]="form.invalid" type="submit" style="width: 200px">Submit form</button>
</form>
<br />
<pre>
Pristine: {{ form.pristine }}
Touched: {{ form.touched }}
Dirty: {{ form.dirty }}
Valid: {{ form.valid }}
Data: {{ form.value | json }}
</pre>
22 changes: 20 additions & 2 deletions tinymce-angular-component/src/main/ts/editor/editor.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
/* eslint-disable @typescript-eslint/no-parameter-properties */
import { isPlatformBrowser, CommonModule } from '@angular/common';
import { AfterViewInit, Component, ElementRef, forwardRef, Inject, Input, NgZone, OnDestroy, PLATFORM_ID, InjectionToken, Optional } from '@angular/core';
import {
AfterViewInit,
Component,
ElementRef,
forwardRef,
Inject,
Input,
NgZone,
OnDestroy,
PLATFORM_ID,
InjectionToken,
Optional,
ChangeDetectorRef,
ChangeDetectionStrategy
} from '@angular/core';
import { FormsModule, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject, takeUntil } from 'rxjs';
import { getTinymce } from '../TinyMCE';
Expand All @@ -25,7 +39,8 @@ const EDITOR_COMPONENT_VALUE_ACCESSOR = {
styles: [ ':host { display: block; }' ],
providers: [ EDITOR_COMPONENT_VALUE_ACCESSOR ],
standalone: true,
imports: [ CommonModule, FormsModule ]
imports: [ CommonModule, FormsModule ],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class EditorComponent extends Events implements AfterViewInit, ControlValueAccessor, OnDestroy {

Expand Down Expand Up @@ -77,6 +92,7 @@ export class EditorComponent extends Events implements AfterViewInit, ControlVal
public constructor(
elementRef: ElementRef,
ngZone: NgZone,
private cdRef: ChangeDetectorRef,
@Inject(PLATFORM_ID) private platformId: Object,
@Optional() @Inject(TINYMCE_SCRIPT_SRC) private tinymceScriptSrc?: string
) {
Expand Down Expand Up @@ -187,10 +203,12 @@ export class EditorComponent extends Events implements AfterViewInit, ControlVal

private initEditor(editor: TinyMCEEditor) {
listenTinyMCEEvent(editor, 'blur', this.destroy$).subscribe(() => {
this.cdRef.markForCheck();
this.ngZone.run(() => this.onTouchedCallback());
});

listenTinyMCEEvent(editor, this.modelEvents, this.destroy$).subscribe(() => {
this.cdRef.markForCheck();
this.ngZone.run(() => this.emitOnChange(editor));
});

Expand Down

0 comments on commit 76e0e52

Please sign in to comment.