Skip to content

Commit 67f04a0

Browse files
INT-2974: Support OnPush change detection (#368)
* 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 <thespyder@programmer.net> --------- Co-authored-by: Andrew Herron <thespyder@programmer.net>
1 parent 14f69d7 commit 67f04a0

File tree

5 files changed

+88
-2
lines changed

5 files changed

+88
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Usage of RxJS deprecated operators. #INT-3274
1414
### Added
1515
- Support for Angular 15, 16 & 17. #INT-3274
16+
- Support for the OnPush change detection strategy. #INT-2974
1617
### Improved
1718
- Updated Storybook to v8, as well as now using CSFv3 components. #INT-3274
1819

stories/Editor.stories.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
55
import { EventBindingComponent } from './event-binding/EventBinding.component';
66
import { EventForwardingComponent } from './event-forwarding/EventForwarding.component';
77
import { FormControlComponent } from './form-control/FormControl.component';
8+
import { FormWithOnPushComponent } from './form-with-on-push/form-with-on-push.component';
89
import { BlogComponent } from './formvalidation/FormValidation.component';
910
import { DisablingComponent } from './disable/Disable.component';
1011
import { ViewQueryComponent } from './viewquery/Viewquery.component';
@@ -97,6 +98,17 @@ export const FormControlStory: StoryObj<EditorComponent> = {
9798
}
9899
};
99100

101+
export const FormStateStory: StoryObj<EditorComponent> = {
102+
name: 'Form with on-push change detection',
103+
render: () => ({
104+
moduleMetadata: {
105+
imports: [ ReactiveFormsModule, FormsModule ],
106+
declarations: [ FormWithOnPushComponent ],
107+
},
108+
template: `<form-with-on-push apiKey="${apiKey}"/>`
109+
}),
110+
};
111+
100112
export const FormValidationStory: StoryObj<EditorComponent> = {
101113
name: 'Form Validation',
102114
render: () => ({
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* eslint-disable @typescript-eslint/unbound-method */
2+
/* eslint-disable @typescript-eslint/no-parameter-properties */
3+
import {
4+
Component,
5+
ChangeDetectionStrategy,
6+
Input,
7+
} from '@angular/core';
8+
import { FormControl, FormGroup, Validators } from '@angular/forms';
9+
import type { EditorComponent } from '../../tinymce-angular-component/src/main/ts/public_api';
10+
11+
@Component({
12+
selector: 'form-with-on-push',
13+
templateUrl: './form-with-on-push.html',
14+
changeDetection: ChangeDetectionStrategy.OnPush,
15+
})
16+
export class FormWithOnPushComponent {
17+
@Input() public apiKey = '';
18+
public readonly initialValue = '';
19+
public readonly init: EditorComponent['init'] = {
20+
plugins: [ 'help' ],
21+
};
22+
public readonly form = new FormGroup({
23+
tiny: new FormControl('', {
24+
validators: Validators.compose([
25+
Validators.required,
26+
Validators.minLength(10)
27+
]),
28+
}),
29+
regular: new FormControl(''),
30+
});
31+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<form [formGroup]="form" style="display: flex; gap: 0.2em; flex-direction: column;">
2+
<editor
3+
formControlName="tiny"
4+
plugins="table"
5+
init="{ width: '200px', }"
6+
/>
7+
<br />
8+
<label>
9+
<span>Regular input</span>
10+
<br />
11+
<input type="text" formControlName="regular" />
12+
</label>
13+
<br />
14+
<button type="reset" style="width: 200px">Reset form</button>
15+
<button [disabled]="form.invalid" type="submit" style="width: 200px">Submit form</button>
16+
</form>
17+
<br />
18+
<pre>
19+
Pristine: {{ form.pristine }}
20+
Touched: {{ form.touched }}
21+
Dirty: {{ form.dirty }}
22+
Valid: {{ form.valid }}
23+
Data: {{ form.value | json }}
24+
</pre>

tinymce-angular-component/src/main/ts/editor/editor.component.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
/* eslint-disable @typescript-eslint/no-parameter-properties */
22
import { isPlatformBrowser, CommonModule } from '@angular/common';
3-
import { AfterViewInit, Component, ElementRef, forwardRef, Inject, Input, NgZone, OnDestroy, PLATFORM_ID, InjectionToken, Optional } from '@angular/core';
3+
import {
4+
AfterViewInit,
5+
Component,
6+
ElementRef,
7+
forwardRef,
8+
Inject,
9+
Input,
10+
NgZone,
11+
OnDestroy,
12+
PLATFORM_ID,
13+
InjectionToken,
14+
Optional,
15+
ChangeDetectorRef,
16+
ChangeDetectionStrategy
17+
} from '@angular/core';
418
import { FormsModule, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
519
import { Subject, takeUntil } from 'rxjs';
620
import { getTinymce } from '../TinyMCE';
@@ -25,7 +39,8 @@ const EDITOR_COMPONENT_VALUE_ACCESSOR = {
2539
styles: [ ':host { display: block; }' ],
2640
providers: [ EDITOR_COMPONENT_VALUE_ACCESSOR ],
2741
standalone: true,
28-
imports: [ CommonModule, FormsModule ]
42+
imports: [ CommonModule, FormsModule ],
43+
changeDetection: ChangeDetectionStrategy.OnPush
2944
})
3045
export class EditorComponent extends Events implements AfterViewInit, ControlValueAccessor, OnDestroy {
3146

@@ -77,6 +92,7 @@ export class EditorComponent extends Events implements AfterViewInit, ControlVal
7792
public constructor(
7893
elementRef: ElementRef,
7994
ngZone: NgZone,
95+
private cdRef: ChangeDetectorRef,
8096
@Inject(PLATFORM_ID) private platformId: Object,
8197
@Optional() @Inject(TINYMCE_SCRIPT_SRC) private tinymceScriptSrc?: string
8298
) {
@@ -187,10 +203,12 @@ export class EditorComponent extends Events implements AfterViewInit, ControlVal
187203

188204
private initEditor(editor: TinyMCEEditor) {
189205
listenTinyMCEEvent(editor, 'blur', this.destroy$).subscribe(() => {
206+
this.cdRef.markForCheck();
190207
this.ngZone.run(() => this.onTouchedCallback());
191208
});
192209

193210
listenTinyMCEEvent(editor, this.modelEvents, this.destroy$).subscribe(() => {
211+
this.cdRef.markForCheck();
194212
this.ngZone.run(() => this.emitOnChange(editor));
195213
});
196214

0 commit comments

Comments
 (0)