From 21c61e33aaf9cc6c6c75d333b510487c2d31ae68 Mon Sep 17 00:00:00 2001 From: Maxime Robert Date: Tue, 22 Dec 2020 11:58:21 +0100 Subject: [PATCH] fix(rewrite): custom change detection with OnPush https://github.com/cloudnc/ngx-sub-form/issues/93 --- projects/ngx-sub-form/src/lib/ngx-sub-form.ts | 27 +++++++------------ .../assassin-droid.component.ts | 3 ++- .../astromech-droid.component.ts | 3 ++- .../droid-listing/droid-product.component.ts | 3 ++- .../medical-droid/medical-droid.component.ts | 3 ++- .../protocol-droid.component.ts | 3 ++- .../listing-form/listing-form.component.ts | 3 ++- .../crew-member/crew-member.component.ts | 3 ++- .../crew-members/crew-members.component.ts | 5 ++-- .../spaceship/spaceship.component.ts | 3 ++- .../speeder/speeder.component.ts | 3 ++- .../vehicle-product.component.ts | 3 ++- .../main-rewrite/listing/listing.component.ts | 3 ++- .../listings/listings.component.ts | 5 ++-- src/app/main-rewrite/main.component.ts | 3 ++- 15 files changed, 40 insertions(+), 33 deletions(-) diff --git a/projects/ngx-sub-form/src/lib/ngx-sub-form.ts b/projects/ngx-sub-form/src/lib/ngx-sub-form.ts index 7fbf0704..ed2698d1 100644 --- a/projects/ngx-sub-form/src/lib/ngx-sub-form.ts +++ b/projects/ngx-sub-form/src/lib/ngx-sub-form.ts @@ -1,3 +1,4 @@ +import { ɵmarkDirty as markDirty } from '@angular/core'; import { FormControl } from '@angular/forms'; import isEqual from 'fast-deep-equal'; import { getObservableLifecycle } from 'ngx-observable-lifecycle'; @@ -15,13 +16,6 @@ import { tap, withLatestFrom, } from 'rxjs/operators'; -import { - ArrayPropertyValue, - isNullOrUndefined, - OneOfControlsTypes, - TypedAbstractControl, - TypedFormControl, -} from './shared/ngx-sub-form-utils'; import { createFormDataFromOptions, getControlValueAccessorBindings, @@ -32,7 +26,6 @@ import { import { ComponentHooks, ControlValueAccessorComponentInstance, - CreateFormArrayControlMethod, FormBindings, FormType, NgxFormOptions, @@ -42,6 +35,7 @@ import { NgxSubFormArrayOptions, NgxSubFormOptions, } from './ngx-sub-form.types'; +import { isNullOrUndefined } from './shared/ngx-sub-form-utils'; const optionsHaveInstructionsToCreateArrays = ( options: NgxFormOptions & Partial>, @@ -212,17 +206,16 @@ export function createForm( handleFormArrays(formArrays, value, createFormArrayControl); formGroup.reset(value, { emitEvent: false }); - - // commenting out the following for now as it seems that calling - // `markDirty` on a component when an input hasn't been set - // (in this case on a root form) then it throws an error - // Cannot read property 'nodeIndex' of null - // so we'll see later on if this is really needed or if it can - // be removed + }), + ), + supportChangeDetectionStrategyOnPush: controlValue$.pipe( + delay(0), + tap(() => // support `changeDetection: ChangeDetectionStrategy.OnPush` // on the component hosting a form - // markDirty(componentInstance); - }), + // fixes https://github.com/cloudnc/ngx-sub-form/issues/93 + markDirty(componentInstance), + ), ), setDisabledState$: setDisabledState$.pipe( tap((shouldDisable: boolean) => { diff --git a/src/app/main-rewrite/listing/listing-form/droid-listing/assassin-droid/assassin-droid.component.ts b/src/app/main-rewrite/listing/listing-form/droid-listing/assassin-droid/assassin-droid.component.ts index 736c2233..433409c6 100644 --- a/src/app/main-rewrite/listing/listing-form/droid-listing/assassin-droid/assassin-droid.component.ts +++ b/src/app/main-rewrite/listing/listing-form/droid-listing/assassin-droid/assassin-droid.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { AssassinDroid, AssassinDroidWeapon, DroidType } from 'src/app/interfaces/droid.interface'; @@ -15,6 +15,7 @@ export const ASSASSIN_DROID_WEAPON_TEXT: { [K in AssassinDroidWeapon]: string } templateUrl: './assassin-droid.component.html', styleUrls: ['./assassin-droid.component.scss'], providers: subformComponentProviders(AssassinDroidComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class AssassinDroidComponent { public AssassinDroidWeapon = AssassinDroidWeapon; diff --git a/src/app/main-rewrite/listing/listing-form/droid-listing/astromech-droid/astromech-droid.component.ts b/src/app/main-rewrite/listing/listing-form/droid-listing/astromech-droid/astromech-droid.component.ts index 990d3257..0b312862 100644 --- a/src/app/main-rewrite/listing/listing-form/droid-listing/astromech-droid/astromech-droid.component.ts +++ b/src/app/main-rewrite/listing/listing-form/droid-listing/astromech-droid/astromech-droid.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { AstromechDroid, AstromechDroidShape, DroidType } from '../../../../../interfaces/droid.interface'; @@ -8,6 +8,7 @@ import { AstromechDroid, AstromechDroidShape, DroidType } from '../../../../../i templateUrl: './astromech-droid.component.html', styleUrls: ['./astromech-droid.component.scss'], providers: subformComponentProviders(AstromechDroidComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class AstromechDroidComponent { public AstromechDroidShape = AstromechDroidShape; diff --git a/src/app/main-rewrite/listing/listing-form/droid-listing/droid-product.component.ts b/src/app/main-rewrite/listing/listing-form/droid-listing/droid-product.component.ts index aa959a68..d3bf5944 100644 --- a/src/app/main-rewrite/listing/listing-form/droid-listing/droid-product.component.ts +++ b/src/app/main-rewrite/listing/listing-form/droid-listing/droid-product.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { @@ -24,6 +24,7 @@ interface OneDroidForm { templateUrl: './droid-product.component.html', styleUrls: ['./droid-product.component.scss'], providers: subformComponentProviders(DroidProductComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class DroidProductComponent { public DroidType = DroidType; diff --git a/src/app/main-rewrite/listing/listing-form/droid-listing/medical-droid/medical-droid.component.ts b/src/app/main-rewrite/listing/listing-form/droid-listing/medical-droid/medical-droid.component.ts index d4826fab..5d0cfd66 100644 --- a/src/app/main-rewrite/listing/listing-form/droid-listing/medical-droid/medical-droid.component.ts +++ b/src/app/main-rewrite/listing/listing-form/droid-listing/medical-droid/medical-droid.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { DroidType, MedicalDroid } from 'src/app/interfaces/droid.interface'; @@ -8,6 +8,7 @@ import { DroidType, MedicalDroid } from 'src/app/interfaces/droid.interface'; templateUrl: './medical-droid.component.html', styleUrls: ['./medical-droid.component.scss'], providers: subformComponentProviders(MedicalDroidComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class MedicalDroidComponent { public form = createForm(this, { diff --git a/src/app/main-rewrite/listing/listing-form/droid-listing/protocol-droid/protocol-droid.component.ts b/src/app/main-rewrite/listing/listing-form/droid-listing/protocol-droid/protocol-droid.component.ts index 84fa869a..88a25817 100644 --- a/src/app/main-rewrite/listing/listing-form/droid-listing/protocol-droid/protocol-droid.component.ts +++ b/src/app/main-rewrite/listing/listing-form/droid-listing/protocol-droid/protocol-droid.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { getObservableLifecycle } from 'ngx-observable-lifecycle'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; @@ -9,6 +9,7 @@ import { DroidType, Languages, ProtocolDroid } from '../../../../../interfaces/d templateUrl: './protocol-droid.component.html', styleUrls: ['./protocol-droid.component.scss'], providers: subformComponentProviders(ProtocolDroidComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ProtocolDroidComponent { public Languages = Languages; diff --git a/src/app/main-rewrite/listing/listing-form/listing-form.component.ts b/src/app/main-rewrite/listing/listing-form/listing-form.component.ts index 1eb6f201..5b2b058f 100644 --- a/src/app/main-rewrite/listing/listing-form/listing-form.component.ts +++ b/src/app/main-rewrite/listing/listing-form/listing-form.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, Output } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType } from 'ngx-sub-form'; import { Subject } from 'rxjs'; @@ -21,6 +21,7 @@ interface OneListingForm { selector: 'app-listing-form', templateUrl: './listing-form.component.html', styleUrls: ['./listing-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ListingFormComponent { public ListingType: typeof ListingType = ListingType; diff --git a/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-member/crew-member.component.ts b/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-member/crew-member.component.ts index 37e0ef28..e19529b1 100644 --- a/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-member/crew-member.component.ts +++ b/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-member/crew-member.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { CrewMember } from '../../../../../../interfaces/crew-member.interface'; @@ -8,6 +8,7 @@ import { CrewMember } from '../../../../../../interfaces/crew-member.interface'; templateUrl: './crew-member.component.html', styleUrls: ['./crew-member.component.scss'], providers: subformComponentProviders(CrewMemberComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class CrewMemberComponent { public form = createForm(this, { diff --git a/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.ts b/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.ts index 434ecdb0..47c8c1ed 100644 --- a/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.ts +++ b/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.ts @@ -1,6 +1,6 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormArray, FormControl, Validators } from '@angular/forms'; -import { ArrayPropertyKey, ArrayPropertyValue, createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; +import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { CrewMember } from '../../../../../interfaces/crew-member.interface'; interface CrewMembersForm { @@ -12,6 +12,7 @@ interface CrewMembersForm { templateUrl: './crew-members.component.html', styleUrls: ['./crew-members.component.scss'], providers: subformComponentProviders(CrewMembersComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class CrewMembersComponent { public form = createForm(this, { diff --git a/src/app/main-rewrite/listing/listing-form/vehicle-listing/spaceship/spaceship.component.ts b/src/app/main-rewrite/listing/listing-form/vehicle-listing/spaceship/spaceship.component.ts index b55b3c7e..a0b948a3 100644 --- a/src/app/main-rewrite/listing/listing-form/vehicle-listing/spaceship/spaceship.component.ts +++ b/src/app/main-rewrite/listing/listing-form/vehicle-listing/spaceship/spaceship.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { Spaceship, VehicleType } from 'src/app/interfaces/vehicle.interface'; @@ -8,6 +8,7 @@ import { Spaceship, VehicleType } from 'src/app/interfaces/vehicle.interface'; templateUrl: './spaceship.component.html', styleUrls: ['./spaceship.component.scss'], providers: subformComponentProviders(SpaceshipComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class SpaceshipComponent { public form = createForm(this, { diff --git a/src/app/main-rewrite/listing/listing-form/vehicle-listing/speeder/speeder.component.ts b/src/app/main-rewrite/listing/listing-form/vehicle-listing/speeder/speeder.component.ts index 61285f33..4b4f6eb5 100644 --- a/src/app/main-rewrite/listing/listing-form/vehicle-listing/speeder/speeder.component.ts +++ b/src/app/main-rewrite/listing/listing-form/vehicle-listing/speeder/speeder.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { Speeder, VehicleType } from 'src/app/interfaces/vehicle.interface'; @@ -8,6 +8,7 @@ import { Speeder, VehicleType } from 'src/app/interfaces/vehicle.interface'; templateUrl: './speeder.component.html', styleUrls: ['./speeder.component.scss'], providers: subformComponentProviders(SpeederComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class SpeederComponent { public form = createForm(this, { diff --git a/src/app/main-rewrite/listing/listing-form/vehicle-listing/vehicle-product.component.ts b/src/app/main-rewrite/listing/listing-form/vehicle-listing/vehicle-product.component.ts index fa3893ec..275569d1 100644 --- a/src/app/main-rewrite/listing/listing-form/vehicle-listing/vehicle-product.component.ts +++ b/src/app/main-rewrite/listing/listing-form/vehicle-listing/vehicle-product.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { createForm, FormType, subformComponentProviders } from 'ngx-sub-form'; import { OneVehicle, Spaceship, Speeder, VehicleType } from 'src/app/interfaces/vehicle.interface'; @@ -15,6 +15,7 @@ export interface OneVehicleForm { templateUrl: './vehicle-product.component.html', styleUrls: ['./vehicle-product.component.scss'], providers: subformComponentProviders(VehicleProductComponent), + changeDetection: ChangeDetectionStrategy.OnPush, }) export class VehicleProductComponent { public VehicleType = VehicleType; diff --git a/src/app/main-rewrite/listing/listing.component.ts b/src/app/main-rewrite/listing/listing.component.ts index db5ae551..7bab88c4 100644 --- a/src/app/main-rewrite/listing/listing.component.ts +++ b/src/app/main-rewrite/listing/listing.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormControl } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { NullableObject } from 'ngx-sub-form'; @@ -12,6 +12,7 @@ import { UuidService } from '../../services/uuid.service'; selector: 'app-listing', templateUrl: './listing.component.html', styleUrls: ['./listing.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ListingComponent { public readonlyFormControl: FormControl = new FormControl(false); diff --git a/src/app/main-rewrite/listings/listings.component.ts b/src/app/main-rewrite/listings/listings.component.ts index 49eb971d..a792731e 100644 --- a/src/app/main-rewrite/listings/listings.component.ts +++ b/src/app/main-rewrite/listings/listings.component.ts @@ -1,12 +1,13 @@ -import { Component, Input } from '@angular/core'; -import { OneListing, ListingType } from '../../interfaces/listing.interface'; +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { DroidType } from 'src/app/interfaces/droid.interface'; import { VehicleType } from 'src/app/interfaces/vehicle.interface'; +import { ListingType, OneListing } from '../../interfaces/listing.interface'; @Component({ selector: 'app-listings', templateUrl: './listings.component.html', styleUrls: ['./listings.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ListingsComponent { @Input() listings: OneListing[] = []; diff --git a/src/app/main-rewrite/main.component.ts b/src/app/main-rewrite/main.component.ts index 1c42a292..4067d7de 100644 --- a/src/app/main-rewrite/main.component.ts +++ b/src/app/main-rewrite/main.component.ts @@ -1,10 +1,11 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ListingService } from '../services/listing.service'; @Component({ selector: 'app-main', templateUrl: './main.component.html', styleUrls: ['./main.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class MainComponent { public listings$ = this.listingService.getListings();