Skip to content

Commit

Permalink
Improve angular performance
Browse files Browse the repository at this point in the history
Improve performance by avoiding unnecessary cloning of the form wide state and avoiding
unnecessary recalculation of the child render props, therefore avoiding unnecessary
change detection cycles in children.

When querying the state from the `JsonFormsAngularService` via its `getState` method, the
whole state is cloned. This lead to a heavy performance penalty because the
`JsonFormsAbstractControl` queried the state on every change detection cycle to get the
global config. The `NumberControlRenderer` queried the state on every change detection
cycle to get the locale. Therefore new methods to receive the config and locale are added
which avoid cloning the whole state.

Signed-off-by: Lucas Koehler <lkoehler@eclipsesource.com>
  • Loading branch information
lucas-koehler authored Oct 31, 2022
1 parent 7206141 commit 708ab2d
Show file tree
Hide file tree
Showing 12 changed files with 42 additions and 21 deletions.
3 changes: 1 addition & 2 deletions packages/angular-material/src/controls/number.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { JsonFormsAngularService, JsonFormsControl } from '@jsonforms/angular';
import {
getLocale,
isIntegerControl,
isNumberControl,
or,
Expand Down Expand Up @@ -140,7 +139,7 @@ export class NumberControlRenderer extends JsonFormsControl {
this.max = this.scopedSchema.maximum;
this.multipleOf = this.scopedSchema.multipleOf || defaultStep;
const appliedUiSchemaOptions = merge({}, props.config, this.uischema.options);
const currentLocale = getLocale(this.jsonFormsService.getState());
const currentLocale = this.jsonFormsService.getLocale();
if (this.locale === undefined || this.locale !== currentLocale) {
this.locale = currentLocale;
this.numberFormat = new Intl.NumberFormat(this.locale, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { JsonFormsAngularService } from '@jsonforms/angular';
template: `
<mat-card fxLayout="column" [fxHide]="hidden">
<mat-card-title class="mat-title">{{ label }}</mat-card-title>
<div *ngFor="let props of renderProps; trackBy: trackElement" fxFlex>
<div *ngFor="let props of uischema | layoutChildrenRenderProps: schema: path; trackBy: trackElement" fxFlex>
<jsonforms-outlet [renderProps]="props"></jsonforms-outlet>
</div>
</mat-card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { JsonFormsAngularService } from '@jsonforms/angular';
[fxHide]="hidden"
fxLayoutAlign="center start"
>
<div *ngFor="let props of renderProps; trackBy: trackElement" fxFlex>
<div *ngFor="let props of uischema | layoutChildrenRenderProps: schema: path; trackBy: trackElement" fxFlex>
<jsonforms-outlet [renderProps]="props"></jsonforms-outlet>
</div>
</div>
Expand Down
29 changes: 17 additions & 12 deletions packages/angular-material/src/layouts/layout.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import { OnDestroy, OnInit, ChangeDetectorRef, Component } from '@angular/core';
import { OnDestroy, OnInit, ChangeDetectorRef, Component, PipeTransform, Pipe } from '@angular/core';
import {
JsonFormsAngularService,
JsonFormsBaseRenderer
Expand All @@ -32,7 +32,8 @@ import {
Layout,
mapStateToLayoutProps,
OwnPropsOfRenderer,
UISchemaElement
UISchemaElement,
JsonSchema
} from '@jsonforms/core';
import { Subscription } from 'rxjs';

Expand Down Expand Up @@ -66,20 +67,24 @@ export class LayoutRenderer<T extends Layout> extends JsonFormsBaseRenderer<T>
}
}

get renderProps(): OwnPropsOfRenderer[] {
const elements = (this.uischema.elements || []).map(
trackElement(_index: number, renderProp: OwnPropsOfRenderer): string {
return renderProp
? renderProp.path + JSON.stringify(renderProp.uischema)
: null;
}
}

@Pipe({ name: 'layoutChildrenRenderProps' })
export class LayoutChildrenRenderPropsPipe implements PipeTransform {
transform(uischema: Layout, schema: JsonSchema, path: string): OwnPropsOfRenderer[] {
const elements = (uischema.elements || []).map(
(el: UISchemaElement) => ({
uischema: el,
schema: this.schema,
path: this.path
schema: schema,
path: path
})
);
return elements;
}

trackElement(_index: number, renderProp: OwnPropsOfRenderer): string {
return renderProp
? renderProp.path + JSON.stringify(renderProp.uischema)
: null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { JsonFormsAngularService } from '@jsonforms/angular';
selector: 'VerticalLayoutRenderer',
template: `
<div fxLayout="column" fxLayoutGap="16px" [fxHide]="hidden">
<div *ngFor="let props of renderProps; trackBy: trackElement" fxFlex>
<div *ngFor="let props of uischema | layoutChildrenRenderProps: schema: path; trackBy: trackElement" fxFlex>
<jsonforms-outlet [renderProps]="props"></jsonforms-outlet>
</div>
</div>
Expand Down
4 changes: 3 additions & 1 deletion packages/angular-material/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import { GroupLayoutRenderer } from './layouts/group-layout.renderer';
import { HorizontalLayoutRenderer } from './layouts/horizontal-layout.renderer';
import { VerticalLayoutRenderer } from './layouts/vertical-layout.renderer';
import { ArrayLayoutRenderer } from './layouts/array-layout.renderer';
import { LayoutChildrenRenderPropsPipe } from './layouts';

@NgModule({
imports: [
Expand Down Expand Up @@ -111,7 +112,8 @@ import { ArrayLayoutRenderer } from './layouts/array-layout.renderer';
ObjectControlRenderer,
AutocompleteControlRenderer,
TableRenderer,
ArrayLayoutRenderer
ArrayLayoutRenderer,
LayoutChildrenRenderPropsPipe
],
entryComponents: [
BooleanControlRenderer,
Expand Down
3 changes: 2 additions & 1 deletion packages/angular-material/test/group-layout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
setupMockStore
} from '@jsonforms/angular-test';
import { FlexLayoutModule } from '@angular/flex-layout';
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';
import {
GroupLayoutRenderer,
groupLayoutTester
Expand All @@ -47,7 +48,7 @@ describe('Group layout', () => {

beforeEach(() => {
fixture = beforeEachLayoutTest(GroupLayoutRenderer, {
declarations: [MatCard, MatCardTitle],
declarations: [LayoutChildrenRenderPropsPipe, MatCard, MatCardTitle],
imports: [FlexLayoutModule]
});
});
Expand Down
2 changes: 2 additions & 0 deletions packages/angular-material/test/horizontal-layout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
HorizontalLayoutRenderer,
horizontalLayoutTester
} from '../src/layouts/horizontal-layout.renderer';
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';

describe('Horizontal layout tester', () => {
it('should succeed', () => {
Expand All @@ -43,6 +44,7 @@ describe('Horizontal layout', () => {

beforeEach(() => {
fixture = beforeEachLayoutTest(HorizontalLayoutRenderer, {
declarations: [LayoutChildrenRenderPropsPipe],
imports: [FlexLayoutModule]
});
});
Expand Down
4 changes: 3 additions & 1 deletion packages/angular-material/test/object-control.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
ObjectControlRendererTester
} from '../src/other/object.renderer';
import { getJsonFormsService } from '@jsonforms/angular-test';
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';

const uischema1: ControlElement = { type: 'Control', scope: '#' };
const uischema2: ControlElement = {
Expand Down Expand Up @@ -98,7 +99,8 @@ describe('Object Control', () => {
ObjectControlRenderer,
TextControlRenderer,
VerticalLayoutRenderer,
GroupLayoutRenderer
GroupLayoutRenderer,
LayoutChildrenRenderPropsPipe
],
imports: [
CommonModule,
Expand Down
2 changes: 2 additions & 0 deletions packages/angular-material/test/vertical-layout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
VerticalLayoutRenderer,
verticalLayoutTester
} from '../src/layouts/vertical-layout.renderer';
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';

describe('Vertical layout tester', () => {
it('should succeed', () => {
Expand All @@ -42,6 +43,7 @@ describe('Vertical layout', () => {

beforeEach(() => {
fixture = beforeEachLayoutTest(VerticalLayoutRenderer, {
declarations: [LayoutChildrenRenderPropsPipe],
imports: [FlexLayoutModule]
});
component = fixture.componentInstance;
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/src/abstract-control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export abstract class JsonFormsAbstractControl<
}

shouldShowUnfocusedDescription(): boolean {
const config = this.jsonFormsService.getState().jsonforms.config;
const config = this.jsonFormsService.getConfig();
const appliedUiSchemaOptions = merge({}, config, this.uischema.options);
return !!appliedUiSchemaOptions.showUnfocusedDescription;
}
Expand Down
8 changes: 8 additions & 0 deletions packages/angular/src/jsonforms.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ export class JsonFormsAngularService {
}
}

getLocale(): string | undefined {
return this._state.i18n?.locale;
}

setLocale(locale: string): void {
this._state.i18n.locale = locale;
this.updateSubject();
Expand All @@ -200,6 +204,10 @@ export class JsonFormsAngularService {
return cloneDeep({ jsonforms: this._state });
}

getConfig(): any {
return cloneDeep(this._state.config)
}

refresh(): void {
this.updateSubject();
}
Expand Down

0 comments on commit 708ab2d

Please sign in to comment.