Skip to content

Commit

Permalink
Fir for issue #197: Alignment of labels within horizontal layouts
Browse files Browse the repository at this point in the history
* Fix for #197: handle control alignment semantics when dealing with configurable label alignments

* Fix for #197: Fix test case
  • Loading branch information
edgarmueller committed Apr 7, 2016
1 parent e04ef78 commit 4e66ed5
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 15 deletions.
1 change: 0 additions & 1 deletion components/renderers/controls/array/array-renderer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ describe('Array renderer', () => {
let el = $compile('<jsonforms schema="schema" ui-schema="uiSchema" data="data"/>')(scope);
scope.$digest();
let fieldSet = angular.element(el[0].getElementsByTagName("fieldset"));
console.log(fieldSet);
expect(fieldSet.attr("disabled")).toBeDefined();
}));
});
2 changes: 1 addition & 1 deletion components/renderers/controls/control.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="col-sm-{{element.size}} jsf-control form-group top-buffer" ng-hide="element.hide">
<div class="row">
<label ng-if="element.label" for="{{element.id}}">{{element.label}}</label>
<label ng-if="element.showLabel" for="{{element.id}}">{{element.label}}</label>
</div>
<div class="row" ng-transclude>
</div>
Expand Down
3 changes: 2 additions & 1 deletion components/renderers/jsonforms-renderers.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ declare module JSONForms {

export interface IRenderDescription {
type: string
size: number
template?: string
templateUrl?: string
size: number
rule?: IRule;
showLabel?: boolean
}

export interface IControlRenderDescription extends IRenderDescription {
Expand Down
68 changes: 57 additions & 11 deletions components/renderers/jsonforms-renderers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,46 @@ module JSONForms {
return new ControlRenderDescription(schemaPath, services, element);
}

// TODO doc
/**
* This is a helper method typically used by layouts that render their contained children in a horizontal
* fashion. In contrast to {@link renderElements} this function also takes into account whether labels
* of controls should be rendered at all, which might be the case if the UI schema declaration states that
* the label for each control is not to be shown.
*
* @param elements the UI schema children elements to be rendered
* @param renderService the RenderService that is used to render the UI schema elements
* @param services the service registry
* @returns {*[]} an array of RenderDescription objects that describe the UI schema elements to be rendered
*/
static renderElementsHorizontally(elements:IUISchemaElement[], renderService: JSONForms.IRenderService, services:JSONForms.Services):JSONForms.IRenderDescription[] {

let labelExists = elements.reduce((atLeastOneLabel, element) => {
return atLeastOneLabel || LabelObjectUtil.shouldShowLabel(element.label);
}, false);

return elements.map(element => {
let renderDesc = renderService.render(
services.get<JSONForms.IScopeProvider>(ServiceId.ScopeProvider).getScope(),
element,
services);
renderDesc.showLabel = labelExists;
return renderDesc;
});
}

/**
* This is a helper method typically used by layouts to render their contained children.
*
* @param elements the UI schema children elements to be rendered
* @param renderService the RenderService that is used to render the UI schema elements
* @param services the service registry
* @returns {*[]} an array of RenderDescription objects that describe the UI schema elements to be rendered
*/
static renderElements(elements:IUISchemaElement[], renderService: JSONForms.IRenderService, services:JSONForms.Services):JSONForms.IRenderDescription[] {
return elements.map((el) => {
return elements.map(element => {
return renderService.render(
services.get<JSONForms.IScopeProvider>(ServiceId.ScopeProvider).getScope(),
el,
element,
services);
});
}
Expand Down Expand Up @@ -100,11 +134,11 @@ module JSONForms {
public size = 100;
public alerts: any[] = []; // TODO IAlert type missing
public label: string;
public showLabel: boolean;
public rule: IRule;
public readOnly: boolean;
public path: string;
public instance: any;

private schema: SchemaElement;
private validationService: IValidationService;
private pathResolver: IPathResolver;
Expand All @@ -121,20 +155,18 @@ module JSONForms {

this.path = PathUtil.normalize(schemaPath);
this.label = this.createLabel(schemaPath, element.label);
// by default labels are shown
this.showLabel = LabelObjectUtil.shouldShowLabel(element.label);
this.readOnly = element.readOnly;
this.rule = element.rule;
this.ruleService.addRuleTrack(this);
this.setupModelChangedCallback();
}

private createLabel(schemaPath:string, label?:IWithLabel):string {
var stringBuilder = "";
private createLabel(schemaPath:string, label: IWithLabel):string {

var labelObject = LabelObjectUtil.getElementLabelObject(label, schemaPath);

if (labelObject.show) {
stringBuilder += labelObject.text;
}
let labelObject = LabelObjectUtil.getElementLabelObject(label, schemaPath);
let stringBuilder = labelObject.text;

if (this.isRequired(schemaPath)) {
stringBuilder += "*";
Expand Down Expand Up @@ -197,6 +229,20 @@ module JSONForms {
}

export class LabelObjectUtil {

public static shouldShowLabel(label: IWithLabel): boolean {
if (label === undefined ) {
return true;
} else if (typeof label === 'boolean') {
return <boolean> label;
} else if (typeof label === 'string') {
return (<string> label) != "";
} else {
let labelObj = <ILabelObject> label;
return labelObj.hasOwnProperty("show") ? labelObj.show : true;
}
}

public static getElementLabelObject(labelProperty:IWithLabel, schemaPath:string):ILabelObject {
if (typeof labelProperty === "boolean") {
if (labelProperty) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/// <reference path="../../../references.ts"/>

describe('HorizontalLayout', () => {

// load all necessary modules and templates
beforeEach(module('jsonforms.form'));
beforeEach(module('jsonforms.renderers.layouts.horizontal'));
beforeEach(module('jsonforms.renderers.controls.string'));

beforeEach(module('components/form/form.html'));
beforeEach(module('components/renderers/layouts/layout.html'));
beforeEach(module('components/renderers/controls/control.html'));

it("should take into account if some labels are hidden", inject(($rootScope, $compile) => {
let scope = $rootScope.$new();
scope.schema = {
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
}
};
scope.uiSchema = {
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"label": true,
"scope": { "$ref": "#/properties/foo" }
},
{
"type": "Control",
"label": false,
"scope": { "$ref": "#/properties/bar" }
}
]
};

scope.data = { "foo": "quux", "bar": "baz" };
let el = $compile('<jsonforms schema="schema" ui-schema="uiSchema" data="data"/>')(scope);
scope.$digest();
let labelElements = el.find('label');
expect(labelElements).toBeDefined();
// one label is empty
expect(labelElements.length).toEqual(2);
expect(angular.element(labelElements[0]).text()).toEqual("Foo");
expect(angular.element(labelElements[1]).text()).toEqual("");
}));

it("should take into account if all labels are hidden", inject(($rootScope, $compile) => {
let scope = $rootScope.$new();
scope.schema = {
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
}
};
scope.uiSchema = {
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"label": {
show: false
},
"scope": { "$ref": "#/properties/foo" }
},
{
"type": "Control",
"label": {
show: false
},
"scope": { "$ref": "#/properties/bar" }
}
]
};

scope.data = { "foo": "quux", "bar": "baz" };
let el = $compile('<jsonforms schema="schema" ui-schema="uiSchema" data="data"/>')(scope);
scope.$digest();
let labelElements = el.find('label');
expect(labelElements.length).toBe(0);
}));
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class HorizontalRenderer implements JSONForms.IRenderer {

var maxSize = 100;

var renderedElements = JSONForms.RenderDescriptionFactory.renderElements(
var renderedElements = JSONForms.RenderDescriptionFactory.renderElementsHorizontally(
element.elements, this.renderService, services);
var size = renderedElements.length;
var individualSize = Math.floor(maxSize / size);
Expand Down

0 comments on commit 4e66ed5

Please sign in to comment.