Skip to content

Commit 3e200d1

Browse files
committed
Fix dynamic title parsing.
1 parent efcace4 commit 3e200d1

13 files changed

+533
-304
lines changed

package-lock.json

Lines changed: 414 additions & 177 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular2-json-schema-form",
3-
"version": "0.6.0-alpha.5",
3+
"version": "0.6.0-alpha.6",
44
"author": {
55
"name": "David Schnell-Davis",
66
"email": "[email protected]"
@@ -55,7 +55,7 @@
5555
"deploy": "firebase deploy"
5656
},
5757
"dependencies": {
58-
"ajv": "^5.3.0",
58+
"ajv": "^5.4.0",
5959
"lodash": "4.x"
6060
},
6161
"peerDependencies": {
@@ -70,8 +70,8 @@
7070
},
7171
"devDependencies": {
7272
"@angular/animations": "^5.0.2",
73-
"@angular/cdk": "^5.0.0-rc0",
74-
"@angular/cli": "^1.5.2",
73+
"@angular/cdk": "5.0.0-rc.1",
74+
"@angular/cli": "^1.5.3",
7575
"@angular/common": "^5.0.2",
7676
"@angular/compiler": "^5.0.2",
7777
"@angular/compiler-cli": "^5.0.2",
@@ -80,18 +80,18 @@
8080
"@angular/forms": "^5.0.2",
8181
"@angular/http": "^5.0.2",
8282
"@angular/language-service": "^5.0.2",
83-
"@angular/material": "^5.0.0-rc0",
83+
"@angular/material": "5.0.0-rc.1",
8484
"@angular/platform-browser": "^5.0.2",
8585
"@angular/platform-browser-dynamic": "^5.0.2",
8686
"@angular/router": "^5.0.2",
8787
"@types/ace": "^0.0.35",
8888
"@types/jasmine": "^2.8.2",
8989
"@types/jasminewd2": "~2.0.2",
9090
"@types/node": "^8.0.53",
91-
"brace": "^0.10.0",
91+
"brace": "^0.11.0",
9292
"camelcase": "^4.0.0",
9393
"codelyzer": "^4.0.1",
94-
"concurrently": "^3.2.0",
94+
"concurrently": "^3.5.1",
9595
"core-js": "^2.4.1",
9696
"glob": "^7.1.1",
9797
"hammerjs": "2.x",
@@ -105,7 +105,7 @@
105105
"karma-jasmine-html-reporter": "^0.2.2",
106106
"protractor": "^5.2.0",
107107
"rimraf": "^2.6.1",
108-
"rollup": "^0.51.7",
108+
"rollup": "^0.51.8",
109109
"rollup-plugin-commonjs": "^8.2.6",
110110
"rollup-plugin-node-resolve": "^3.0.0",
111111
"rollup-plugin-node-resolve-angular": "^2.0.3",

src/lib/src/framework-library/bootstrap-3-framework/bootstrap-3-framework.component.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,8 @@ export class Bootstrap3FrameworkComponent implements OnInit, OnChanges {
276276

277277
setTitle(): string {
278278
switch (this.layoutNode.type) {
279-
case 'button': case 'checkbox': case 'help': case 'msg':
280-
case 'message': case 'submit': case 'tabarray': case '$ref':
279+
case 'button': case 'checkbox': case 'section': case 'help': case 'msg':
280+
case 'submit': case 'message': case 'tabarray': case 'tabs': case '$ref':
281281
return null;
282282
case 'advancedfieldset':
283283
this.widgetOptions.expandable = true;
@@ -287,22 +287,9 @@ export class Bootstrap3FrameworkComponent implements OnInit, OnChanges {
287287
this.widgetOptions.expandable = true;
288288
this.widgetOptions.title = 'Authentication settings';
289289
return null;
290-
case 'tabs': case 'section':
291-
return null;
292290
default:
293-
let thisTitle = this.options.title ||
294-
(isNaN(this.layoutNode.name) && this.layoutNode.name !== '-' ?
295-
toTitleCase(this.layoutNode.name) : null);
296291
this.widgetOptions.title = null;
297-
return !thisTitle ? null :
298-
thisTitle.indexOf('{{') === -1 || !this.formControl || !this.dataIndex ?
299-
thisTitle :
300-
this.jsf.parseText(
301-
thisTitle,
302-
this.jsf.getFormControlValue(this),
303-
this.jsf.getFormControlGroup(this).value,
304-
this.dataIndex[this.dataIndex.length - 1]
305-
);
292+
return this.jsf.setItemTitle(this);
306293
}
307294
}
308295

src/lib/src/framework-library/bootstrap-4-framework/bootstrap-4-framework.component.ts

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -208,35 +208,35 @@ export class Bootstrap4FrameworkComponent implements OnInit, OnChanges {
208208
break;
209209
// Button sets - checkboxbuttons and radiobuttons
210210
case 'checkboxbuttons': case 'radiobuttons':
211-
this.widgetOptions.htmlClass = addClasses(
212-
this.widgetOptions.htmlClass, 'btn-group');
213-
this.widgetOptions.itemLabelHtmlClass = addClasses(
214-
this.widgetOptions.itemLabelHtmlClass, 'btn');
215-
this.widgetOptions.itemLabelHtmlClass = addClasses(
216-
this.widgetOptions.itemLabelHtmlClass, this.options.style || 'btn-default');
217-
this.widgetOptions.fieldHtmlClass = addClasses(
218-
this.widgetOptions.fieldHtmlClass, 'sr-only');
211+
this.widgetOptions.htmlClass = addClasses(
212+
this.widgetOptions.htmlClass, 'btn-group');
213+
this.widgetOptions.itemLabelHtmlClass = addClasses(
214+
this.widgetOptions.itemLabelHtmlClass, 'btn');
215+
this.widgetOptions.itemLabelHtmlClass = addClasses(
216+
this.widgetOptions.itemLabelHtmlClass, this.options.style || 'btn-default');
217+
this.widgetOptions.fieldHtmlClass = addClasses(
218+
this.widgetOptions.fieldHtmlClass, 'sr-only');
219219
break;
220220
// Single button controls
221221
case 'button': case 'submit':
222-
this.widgetOptions.fieldHtmlClass = addClasses(
223-
this.widgetOptions.fieldHtmlClass, 'btn');
224-
this.widgetOptions.fieldHtmlClass = addClasses(
225-
this.widgetOptions.fieldHtmlClass, this.options.style || 'btn-info');
222+
this.widgetOptions.fieldHtmlClass = addClasses(
223+
this.widgetOptions.fieldHtmlClass, 'btn');
224+
this.widgetOptions.fieldHtmlClass = addClasses(
225+
this.widgetOptions.fieldHtmlClass, this.options.style || 'btn-info');
226226
break;
227227
// Containers - arrays and fieldsets
228228
case 'array': case 'fieldset': case 'section': case 'conditional':
229229
case 'advancedfieldset': case 'authfieldset':
230230
case 'selectfieldset': case 'optionfieldset':
231-
this.options.messageLocation = 'top';
231+
this.options.messageLocation = 'top';
232232
break;
233233
case 'tabarray': case 'tabs':
234-
this.widgetOptions.htmlClass = addClasses(
235-
this.widgetOptions.htmlClass, 'tab-content');
236-
this.widgetOptions.fieldHtmlClass = addClasses(
237-
this.widgetOptions.fieldHtmlClass, 'tab-pane');
238-
this.widgetOptions.labelHtmlClass = addClasses(
239-
this.widgetOptions.labelHtmlClass, 'nav nav-tabs');
234+
this.widgetOptions.htmlClass = addClasses(
235+
this.widgetOptions.htmlClass, 'tab-content');
236+
this.widgetOptions.fieldHtmlClass = addClasses(
237+
this.widgetOptions.fieldHtmlClass, 'tab-pane');
238+
this.widgetOptions.labelHtmlClass = addClasses(
239+
this.widgetOptions.labelHtmlClass, 'nav nav-tabs');
240240
break;
241241
// 'Add' buttons - references
242242
case '$ref':
@@ -245,7 +245,7 @@ export class Bootstrap4FrameworkComponent implements OnInit, OnChanges {
245245
this.widgetOptions.fieldHtmlClass = addClasses(
246246
this.widgetOptions.fieldHtmlClass, this.options.style || 'btn-default');
247247
this.options.icon = 'glyphicon glyphicon-plus';
248-
break;
248+
break;
249249
// Default - including regular inputs
250250
default:
251251
this.widgetOptions.fieldHtmlClass = addClasses(
@@ -268,17 +268,17 @@ export class Bootstrap4FrameworkComponent implements OnInit, OnChanges {
268268

269269
updateHelpBlock(status) {
270270
this.options.helpBlock = status === 'INVALID' &&
271-
this.options.enableErrorState && this.formControl.errors &&
272-
(this.formControl.dirty || this.options.feedbackOnRender) ?
273-
this.jsf.formatErrors(this.formControl.errors, this.options.validationMessages) :
274-
this.options.description || this.options.help || null;
271+
this.options.enableErrorState && this.formControl.errors &&
272+
(this.formControl.dirty || this.options.feedbackOnRender) ?
273+
this.jsf.formatErrors(this.formControl.errors, this.options.validationMessages) :
274+
this.options.description || this.options.help || null;
275275
}
276276

277277
setTitle(): string {
278278
switch (this.layoutNode.type) {
279-
case 'button': case 'checkbox': case 'help': case 'msg':
280-
case 'message': case 'submit': case 'tabarray': case '$ref':
281-
return null;
279+
case 'button': case 'checkbox': case 'section': case 'help': case 'msg':
280+
case 'submit': case 'message': case 'tabarray': case 'tabs': case '$ref':
281+
return null;
282282
case 'advancedfieldset':
283283
this.widgetOptions.expandable = true;
284284
this.widgetOptions.title = 'Advanced options';
@@ -287,22 +287,9 @@ export class Bootstrap4FrameworkComponent implements OnInit, OnChanges {
287287
this.widgetOptions.expandable = true;
288288
this.widgetOptions.title = 'Authentication settings';
289289
return null;
290-
case 'tabs': case 'section':
291-
return null;
292290
default:
293-
let thisTitle = this.options.title ||
294-
(isNaN(this.layoutNode.name) && this.layoutNode.name !== '-' ?
295-
toTitleCase(this.layoutNode.name) : null);
296291
this.widgetOptions.title = null;
297-
return !thisTitle ? null :
298-
thisTitle.indexOf('{{') === -1 || !this.formControl || !this.dataIndex ?
299-
thisTitle :
300-
this.jsf.parseText(
301-
thisTitle,
302-
this.jsf.getFormControlValue(this),
303-
this.jsf.getFormControlGroup(this).value,
304-
this.dataIndex[this.dataIndex.length - 1]
305-
);
292+
return this.jsf.setItemTitle(this);
306293
}
307294
}
308295

src/lib/src/framework-library/material-design-framework/flex-layout-section.component.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Component, Input, OnInit } from '@angular/core';
22
import { AbstractControl } from '@angular/forms';
33

4+
import { toTitleCase } from '../../shared';
45
import { JsonSchemaFormService } from '../../json-schema-form.service';
56

67
@Component({
@@ -10,10 +11,9 @@ import { JsonSchemaFormService } from '../../json-schema-form.service';
1011
[class]="options?.htmlClass || ''"
1112
[class.expandable]="options?.expandable && !expanded"
1213
[class.expanded]="options?.expandable && expanded">
13-
<label
14+
<label *ngIf="sectionTitle"
1415
[class]="'legend ' + (options?.labelHtmlClass || '')"
15-
[style.display]="(options?.notitle || !options?.title) ? 'none' : ''"
16-
[innerHTML]="options?.title"
16+
[innerHTML]="sectionTitle"
1717
(click)="toggleExpanded()"></label>
1818
<flex-layout-root-widget *ngIf="expanded"
1919
[layout]="layoutNode.items"
@@ -42,10 +42,9 @@ import { JsonSchemaFormService } from '../../json-schema-form.service';
4242
[class.expandable]="options?.expandable && !expanded"
4343
[class.expanded]="options?.expandable && expanded"
4444
[disabled]="options?.readonly">
45-
<legend
45+
<legend *ngIf="sectionTitle"
4646
[class]="'legend ' + (options?.labelHtmlClass || '')"
47-
[style.display]="(options?.notitle || !options?.title) ? 'none' : ''"
48-
[innerHTML]="options?.title"
47+
[innerHTML]="sectionTitle"
4948
(click)="toggleExpanded()"></legend>
5049
<flex-layout-root-widget *ngIf="expanded"
5150
[layout]="layoutNode.items"
@@ -73,11 +72,10 @@ import { JsonSchemaFormService } from '../../json-schema-form.service';
7372
[class]="options?.htmlClass || ''"
7473
[class.expandable]="options?.expandable && !expanded"
7574
[class.expanded]="options?.expandable && expanded">
76-
<mat-card-header>
75+
<mat-card-header *ngIf="sectionTitle">
7776
<legend
7877
[class]="'legend ' + (options?.labelHtmlClass || '')"
79-
[style.display]="(options?.notitle || !options?.title) ? 'none' : ''"
80-
[innerHTML]="options?.title"
78+
[innerHTML]="sectionTitle"
8179
(click)="toggleExpanded()"></legend>
8280
</mat-card-header>
8381
<mat-card-content *ngIf="expanded">
@@ -113,10 +111,9 @@ import { JsonSchemaFormService } from '../../json-schema-form.service';
113111
[hideToggle]="!options?.expandable">
114112
<mat-expansion-panel-header>
115113
<mat-panel-title>
116-
<legend
114+
<legend *ngIf="sectionTitle"
117115
[class]="options?.labelHtmlClass"
118-
[style.display]="(options?.notitle || !options?.title) ? 'none' : ''"
119-
[innerHTML]="options?.title"
116+
[innerHTML]="sectionTitle"
120117
(click)="toggleExpanded()"></legend>
121118
</mat-panel-title>
122119
</mat-expansion-panel-header>
@@ -167,6 +164,10 @@ export class FlexLayoutSectionComponent implements OnInit {
167164
private jsf: JsonSchemaFormService
168165
) { }
169166

167+
get sectionTitle() {
168+
return this.options.notitle ? null : this.jsf.setItemTitle(this);
169+
}
170+
170171
ngOnInit() {
171172
this.jsf.initializeControl(this);
172173
this.options = this.layoutNode.options || {};

src/lib/src/framework-library/material-design-framework/material-add-reference.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ export class MaterialAddReferenceComponent implements OnInit {
5151
layoutNode: this.jsf.getParentNode(this),
5252
};
5353
return parent.layoutNode.add ||
54-
this.jsf.setTitle(parent, this.layoutNode, this.itemCount);
54+
this.jsf.setArrayItemTitle(parent, this.layoutNode, this.itemCount);
5555
}
5656
}

src/lib/src/framework-library/material-design-framework/material-design-framework.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,10 @@ export class MaterialDesignFrameworkComponent implements OnInit, OnChanges {
127127
}
128128

129129
if (
130-
this.layoutNode.type !== 'tabs' &&
131-
this.layoutNode.type !== 'tabarray' &&
132-
(this.widgetOptions.title || '').indexOf('{{') > -1
130+
!['$ref', 'advancedfieldset', 'authfieldset', 'button', 'card',
131+
'checkbox', 'expansion-panel', 'help', 'message', 'msg', 'section',
132+
'submit', 'tabarray', 'tabs'].includes(this.layoutNode.type) &&
133+
/{{.+?}}/.test(this.widgetOptions.title || '')
133134
) {
134135
this.dynamicTitle = this.widgetOptions.title;
135136
this.updateTitle();

src/lib/src/framework-library/material-design-framework/material-tabs.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { JsonSchemaFormService } from '../../json-schema-form.service';
1212
[active]="selectedItem === i"
1313
(click)="select(i)">
1414
<span *ngIf="showAddTab || item.type !== '$ref'"
15-
[innerHTML]="setTitle(item, i)"></span>
15+
[innerHTML]="setTabTitle(item, i)"></span>
1616
</a>
1717
</nav>
1818
<div *ngFor="let layoutItem of layoutNode?.items; let i = index"
@@ -63,7 +63,7 @@ export class MaterialTabsComponent implements OnInit {
6363
this.itemCount < (lastItem.options.maxItems || 1000);
6464
}
6565

66-
setTitle(item: any, index: number): string {
67-
return this.jsf.setTitle(this, item, index);
66+
setTabTitle(item: any, index: number): string {
67+
return this.jsf.setArrayItemTitle(this, item, index);
6868
}
6969
}

src/lib/src/json-schema-form.service.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ export class JsonSchemaFormService {
394394
return '';
395395
}
396396

397-
setTitle(
397+
setArrayItemTitle(
398398
parentCtx: any = {}, childNode: any = null, index: number = null
399399
): string {
400400
const parentNode = parentCtx.layoutNode;
@@ -420,6 +420,17 @@ export class JsonSchemaFormService {
420420
return this.parseText(text, childValue, parentValues, index);
421421
}
422422

423+
setItemTitle(ctx: any) {
424+
return !ctx.options.title && /^(\d+|-)$/.test(ctx.layoutNode.name) ?
425+
null :
426+
this.parseText(
427+
ctx.options.title || toTitleCase(ctx.layoutNode.name),
428+
this.getFormControlValue(this),
429+
(this.getFormControlGroup(this) || <any>{}).value,
430+
ctx.dataIndex[ctx.dataIndex.length - 1]
431+
);
432+
}
433+
423434
initializeControl(ctx: any, bind = true): boolean {
424435
if (!isObject(ctx)) { return false; }
425436
if (isEmpty(ctx.options)) {
@@ -479,7 +490,7 @@ export class JsonSchemaFormService {
479490
// If custom error message is a string, replace placeholders and return
480491
typeof validationMessages[errorKey] === 'string' ?
481492
// Does error message have any {{property}} placeholders?
482-
validationMessages[errorKey].indexOf('{{') === -1 ?
493+
!/{{.+?}}/.test(validationMessages[errorKey]) ?
483494
validationMessages[errorKey] :
484495
// Replace {{property}} placeholders with values
485496
Object.keys(errors[errorKey])

src/lib/src/shared/utility.functions.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
/**
1414
* 'addClasses' function
1515
*
16+
* Merges two space-delimited lists of CSS classes and removes duplicates.
17+
*
1618
* @param {string | string[] | Set<string>} oldClasses
1719
* @param {string | string[] | Set<string>} newClasses
1820
* @return {string | string[] | Set<string>} - Combined classes
@@ -185,9 +187,9 @@ export function hasOwn(object: any, property: string): boolean {
185187
export function mergeFilteredObject(
186188
targetObject: PlainObject,
187189
sourceObject: PlainObject,
188-
excludeKeys: any[] = [],
189-
keyFn: (string: string) => string = (key: string) => key,
190-
valFn: (any: any) => any = (val: any) => val
190+
excludeKeys = <string[]>[],
191+
keyFn = (key: string): string => key,
192+
valFn = (val: any): any => val
191193
): PlainObject {
192194
if (!isObject(sourceObject)) { return targetObject; }
193195
if (!isObject(targetObject)) { targetObject = {}; }

src/lib/src/widget-library/add-reference.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ export class AddReferenceComponent implements OnInit {
4949
layoutNode: this.jsf.getParentNode(this)
5050
};
5151
return parent.layoutNode.add ||
52-
this.jsf.setTitle(parent, this.layoutNode, this.itemCount);
52+
this.jsf.setArrayItemTitle(parent, this.layoutNode, this.itemCount);
5353
}
5454
}

0 commit comments

Comments
 (0)