Skip to content

Commit 708ab2d

Browse files
Improve angular performance
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 <[email protected]>
1 parent 7206141 commit 708ab2d

12 files changed

+42
-21
lines changed

packages/angular-material/src/controls/number.renderer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import { ChangeDetectionStrategy, Component } from '@angular/core';
2626
import { JsonFormsAngularService, JsonFormsControl } from '@jsonforms/angular';
2727
import {
28-
getLocale,
2928
isIntegerControl,
3029
isNumberControl,
3130
or,
@@ -140,7 +139,7 @@ export class NumberControlRenderer extends JsonFormsControl {
140139
this.max = this.scopedSchema.maximum;
141140
this.multipleOf = this.scopedSchema.multipleOf || defaultStep;
142141
const appliedUiSchemaOptions = merge({}, props.config, this.uischema.options);
143-
const currentLocale = getLocale(this.jsonFormsService.getState());
142+
const currentLocale = this.jsonFormsService.getLocale();
144143
if (this.locale === undefined || this.locale !== currentLocale) {
145144
this.locale = currentLocale;
146145
this.numberFormat = new Intl.NumberFormat(this.locale, {

packages/angular-material/src/layouts/group-layout.renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { JsonFormsAngularService } from '@jsonforms/angular';
3232
template: `
3333
<mat-card fxLayout="column" [fxHide]="hidden">
3434
<mat-card-title class="mat-title">{{ label }}</mat-card-title>
35-
<div *ngFor="let props of renderProps; trackBy: trackElement" fxFlex>
35+
<div *ngFor="let props of uischema | layoutChildrenRenderProps: schema: path; trackBy: trackElement" fxFlex>
3636
<jsonforms-outlet [renderProps]="props"></jsonforms-outlet>
3737
</div>
3838
</mat-card>

packages/angular-material/src/layouts/horizontal-layout.renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { JsonFormsAngularService } from '@jsonforms/angular';
4141
[fxHide]="hidden"
4242
fxLayoutAlign="center start"
4343
>
44-
<div *ngFor="let props of renderProps; trackBy: trackElement" fxFlex>
44+
<div *ngFor="let props of uischema | layoutChildrenRenderProps: schema: path; trackBy: trackElement" fxFlex>
4545
<jsonforms-outlet [renderProps]="props"></jsonforms-outlet>
4646
</div>
4747
</div>

packages/angular-material/src/layouts/layout.renderer.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2323
THE SOFTWARE.
2424
*/
25-
import { OnDestroy, OnInit, ChangeDetectorRef, Component } from '@angular/core';
25+
import { OnDestroy, OnInit, ChangeDetectorRef, Component, PipeTransform, Pipe } from '@angular/core';
2626
import {
2727
JsonFormsAngularService,
2828
JsonFormsBaseRenderer
@@ -32,7 +32,8 @@ import {
3232
Layout,
3333
mapStateToLayoutProps,
3434
OwnPropsOfRenderer,
35-
UISchemaElement
35+
UISchemaElement,
36+
JsonSchema
3637
} from '@jsonforms/core';
3738
import { Subscription } from 'rxjs';
3839

@@ -66,20 +67,24 @@ export class LayoutRenderer<T extends Layout> extends JsonFormsBaseRenderer<T>
6667
}
6768
}
6869

69-
get renderProps(): OwnPropsOfRenderer[] {
70-
const elements = (this.uischema.elements || []).map(
70+
trackElement(_index: number, renderProp: OwnPropsOfRenderer): string {
71+
return renderProp
72+
? renderProp.path + JSON.stringify(renderProp.uischema)
73+
: null;
74+
}
75+
}
76+
77+
@Pipe({ name: 'layoutChildrenRenderProps' })
78+
export class LayoutChildrenRenderPropsPipe implements PipeTransform {
79+
transform(uischema: Layout, schema: JsonSchema, path: string): OwnPropsOfRenderer[] {
80+
const elements = (uischema.elements || []).map(
7181
(el: UISchemaElement) => ({
7282
uischema: el,
73-
schema: this.schema,
74-
path: this.path
83+
schema: schema,
84+
path: path
7585
})
7686
);
7787
return elements;
7888
}
7989

80-
trackElement(_index: number, renderProp: OwnPropsOfRenderer): string {
81-
return renderProp
82-
? renderProp.path + JSON.stringify(renderProp.uischema)
83-
: null;
84-
}
85-
}
90+
}

packages/angular-material/src/layouts/vertical-layout.renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { JsonFormsAngularService } from '@jsonforms/angular';
3636
selector: 'VerticalLayoutRenderer',
3737
template: `
3838
<div fxLayout="column" fxLayoutGap="16px" [fxHide]="hidden">
39-
<div *ngFor="let props of renderProps; trackBy: trackElement" fxFlex>
39+
<div *ngFor="let props of uischema | layoutChildrenRenderProps: schema: path; trackBy: trackElement" fxFlex>
4040
<jsonforms-outlet [renderProps]="props"></jsonforms-outlet>
4141
</div>
4242
</div>

packages/angular-material/src/module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import { GroupLayoutRenderer } from './layouts/group-layout.renderer';
6666
import { HorizontalLayoutRenderer } from './layouts/horizontal-layout.renderer';
6767
import { VerticalLayoutRenderer } from './layouts/vertical-layout.renderer';
6868
import { ArrayLayoutRenderer } from './layouts/array-layout.renderer';
69+
import { LayoutChildrenRenderPropsPipe } from './layouts';
6970

7071
@NgModule({
7172
imports: [
@@ -111,7 +112,8 @@ import { ArrayLayoutRenderer } from './layouts/array-layout.renderer';
111112
ObjectControlRenderer,
112113
AutocompleteControlRenderer,
113114
TableRenderer,
114-
ArrayLayoutRenderer
115+
ArrayLayoutRenderer,
116+
LayoutChildrenRenderPropsPipe
115117
],
116118
entryComponents: [
117119
BooleanControlRenderer,

packages/angular-material/test/group-layout.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
setupMockStore
3333
} from '@jsonforms/angular-test';
3434
import { FlexLayoutModule } from '@angular/flex-layout';
35+
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';
3536
import {
3637
GroupLayoutRenderer,
3738
groupLayoutTester
@@ -47,7 +48,7 @@ describe('Group layout', () => {
4748

4849
beforeEach(() => {
4950
fixture = beforeEachLayoutTest(GroupLayoutRenderer, {
50-
declarations: [MatCard, MatCardTitle],
51+
declarations: [LayoutChildrenRenderPropsPipe, MatCard, MatCardTitle],
5152
imports: [FlexLayoutModule]
5253
});
5354
});

packages/angular-material/test/horizontal-layout.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
HorizontalLayoutRenderer,
3131
horizontalLayoutTester
3232
} from '../src/layouts/horizontal-layout.renderer';
33+
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';
3334

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

4445
beforeEach(() => {
4546
fixture = beforeEachLayoutTest(HorizontalLayoutRenderer, {
47+
declarations: [LayoutChildrenRenderPropsPipe],
4648
imports: [FlexLayoutModule]
4749
});
4850
});

packages/angular-material/test/object-control.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
ObjectControlRendererTester
4747
} from '../src/other/object.renderer';
4848
import { getJsonFormsService } from '@jsonforms/angular-test';
49+
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';
4950

5051
const uischema1: ControlElement = { type: 'Control', scope: '#' };
5152
const uischema2: ControlElement = {
@@ -98,7 +99,8 @@ describe('Object Control', () => {
9899
ObjectControlRenderer,
99100
TextControlRenderer,
100101
VerticalLayoutRenderer,
101-
GroupLayoutRenderer
102+
GroupLayoutRenderer,
103+
LayoutChildrenRenderPropsPipe
102104
],
103105
imports: [
104106
CommonModule,

packages/angular-material/test/vertical-layout.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
VerticalLayoutRenderer,
3131
verticalLayoutTester
3232
} from '../src/layouts/vertical-layout.renderer';
33+
import { LayoutChildrenRenderPropsPipe } from '../src/layouts/layout.renderer';
3334

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

4344
beforeEach(() => {
4445
fixture = beforeEachLayoutTest(VerticalLayoutRenderer, {
46+
declarations: [LayoutChildrenRenderPropsPipe],
4547
imports: [FlexLayoutModule]
4648
});
4749
component = fixture.componentInstance;

0 commit comments

Comments
 (0)