Skip to content

Commit

Permalink
Fixes rjsf-team#43: Added support for hidden widgets. r=@magopian
Browse files Browse the repository at this point in the history
  • Loading branch information
n1k0 committed Apr 4, 2016
1 parent 3b11eb4 commit c062b1b
Show file tree
Hide file tree
Showing 13 changed files with 271 additions and 19 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ A [live playground](https://mozilla-services.github.io/react-jsonschema-form/) i
- [For boolean fields](#for-boolean-fields)
- [For string fields](#for-string-fields)
- [For number and integer fields](#for-number-and-integer-fields)
- [Hidden widgets](#hidden-widgets)
- [Object fields ordering](#object-fields-ordering)
- [Custom CSS class names](#custom-css-class-names)
- [Custom labels for enum fields](#custom-labels-for-enum-fields)
Expand Down Expand Up @@ -189,6 +190,28 @@ Here's a list of supported alternative widgets for different JSONSchema data typ

> Note: for numbers, `min`, `max` and `step` input attributes values will be handled according to JSONSchema's `minimum`, `maximium` and `multipleOf` values when they're defined.
#### Hidden widgets

It's possible to use an hidden widget for a given field by setting the `ui:widget` uiSchema directive to `hidden` for this field:

```js
const schema = {
type: "object",
properties: {
foo: {type: "boolean"}
}
};

const uiSchema = {
foo: {"ui:widget": "hidden"}
};
```

> Notes
>
> - Hiding widgets is only supported for `boolean`, `string`, `number`, `integer` and `date-time` schema types;
> - An hidden widget takes its value from the `formData` prop.
### Object fields ordering

The `uiSchema` object spec also allows you to define in which order a given object field properties should be rendered using the `ui:order` property:
Expand Down
10 changes: 9 additions & 1 deletion playground/samples/widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ module.exports = {
title: "textarea"
}
}
},
secret: {
type: "string",
default: "I'm a hidden string."
}
}
},
Expand All @@ -50,6 +54,9 @@ module.exports = {
textarea: {
"ui:widget": "textarea"
}
},
secret: {
"ui:widget": "hidden"
}
},
formData: {
Expand All @@ -61,6 +68,7 @@ module.exports = {
string: {
default: "Hello...",
textarea: "... World"
}
},
secret: "I'm a hidden string."
}
};
7 changes: 7 additions & 0 deletions src/components/fields/SchemaField.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@ function Wrapper({
classNames,
errorSchema,
label,
hidden,
required,
displayLabel,
id,
children,
}) {
if (hidden) {
return children;
}
const {errors} = errorSchema;
const isError = errors && errors.length > 0;
const classList = [
Expand All @@ -89,6 +93,7 @@ if (process.env.NODE_ENV !== "production") {
id: PropTypes.string,
classNames: React.PropTypes.string,
label: PropTypes.string,
hidden: PropTypes.bool,
required: PropTypes.bool,
displayLabel: PropTypes.bool,
children: React.PropTypes.node.isRequired,
Expand All @@ -98,6 +103,7 @@ if (process.env.NODE_ENV !== "production") {
Wrapper.defaultProps = {
classNames: "",
errorSchema: {errors: []},
hidden: false,
required: false,
displayLabel: true,
};
Expand All @@ -124,6 +130,7 @@ function SchemaField(props) {
<Wrapper
label={schema.title || name}
errorSchema={errorSchema}
hidden={uiSchema["ui:widget"] === "hidden"}
required={required}
type={schema.type}
displayLabel={displayLabel}
Expand Down
31 changes: 31 additions & 0 deletions src/components/widgets/HiddenWidget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { PropTypes } from "react";


function HiddenWidget({
id,
value,
defaultValue
}) {
return (
<input type="hidden"
id={id}
value={value}
defaultValue={defaultValue} />
);
}

if (process.env.NODE_ENV !== "production") {
HiddenWidget.propTypes = {
id: PropTypes.string.isRequired,
value: PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
]),
defaultValue: PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
])
};
}

export default HiddenWidget;
8 changes: 8 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import UpDownWidget from "./components/widgets/UpDownWidget";
import RangeWidget from "./components/widgets/RangeWidget";
import SelectWidget from "./components/widgets/SelectWidget";
import TextareaWidget from "./components/widgets/TextareaWidget";
import HiddenWidget from "./components/widgets/HiddenWidget";


const RE_ERROR_ARRAY_PATH = /(.*)\[(\d+)\]$/;
Expand All @@ -14,20 +15,27 @@ const altWidgetMap = {
boolean: {
radio: RadioWidget,
select: SelectWidget,
hidden: HiddenWidget,
},
string: {
password: PasswordWidget,
radio: RadioWidget,
select: SelectWidget,
textarea: TextareaWidget,
hidden: HiddenWidget,
},
number: {
updown: UpDownWidget,
range: RangeWidget,
hidden: HiddenWidget,
},
integer: {
updown: UpDownWidget,
range: RangeWidget,
hidden: HiddenWidget,
},
"date-time": {
hidden: HiddenWidget,
}
};

Expand Down
13 changes: 12 additions & 1 deletion test/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
{
"env": {
"mocha": true
"mocha": true,
},
"globals": {
d: true
},
"rules": {
"no-unused-vars": [
2,
{
"varsIgnorePattern": "^d$"
}
]
}
}
6 changes: 2 additions & 4 deletions test/ArrayField_test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/*eslint no-unused-vars: [2, { "varsIgnorePattern": "^d$" }]*/

import { expect } from "chai";
import { Simulate } from "react-addons-test-utils";

import { createFormComponent, d } from "./test_utils";
import { createFormComponent } from "./test_utils";

describe("ArrayField", () => {
describe("List of inputs", () => {
Expand Down Expand Up @@ -179,7 +177,7 @@ describe("ArrayField", () => {
expect(node.querySelector("select").id).eql("root");
});
});

describe("Nested lists", () => {
const schema = {
"type": "array",
Expand Down
4 changes: 1 addition & 3 deletions test/Form_test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
/*eslint no-unused-vars: [2, { "varsIgnorePattern": "^d$" }]*/

import { expect } from "chai";
import sinon from "sinon";
import React from "react";
import { Simulate, renderIntoDocument } from "react-addons-test-utils";
import { findDOMNode } from "react-dom";

import Form from "../src";
import { createFormComponent, d } from "./test_utils";
import { createFormComponent } from "./test_utils";

describe("Form", () => {
var sandbox;
Expand Down
4 changes: 1 addition & 3 deletions test/ObjectField_test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
/*eslint no-unused-vars: [2, { "varsIgnorePattern": "^d$" }]*/

import React from "react";
import { expect } from "chai";
import { Simulate } from "react-addons-test-utils";

import { createFormComponent, d } from "./test_utils";
import { createFormComponent } from "./test_utils";

describe("ObjectField", () => {
describe("schema", () => {
Expand Down
3 changes: 0 additions & 3 deletions test/performance_test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@

/*eslint no-unused-vars: [2, { "varsIgnorePattern": "^d$" }]*/

import sinon from "sinon";
import React from "react";

Expand Down
5 changes: 5 additions & 0 deletions test/setup-jsdom.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ if (!global.hasOwnProperty("window")) {
global.window = document.defaultView;
global.navigator = global.window.navigator;
}

// HTML debugging helper
global.d = function d(node) {
console.log(require("html").prettyPrint(node.outerHTML, {indent_size: 2}));
};
4 changes: 0 additions & 4 deletions test/test_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,3 @@ export function createComponent(Component, props) {
export function createFormComponent(props) {
return createComponent(Form, props);
}

export function d(node) {
console.log(require("html").prettyPrint(node.outerHTML, {indent_size: 2}));
}
Loading

0 comments on commit c062b1b

Please sign in to comment.