Skip to content

Commit 6fc83b7

Browse files
committed
Fixes #20: Added PasswordWidget.
1 parent 3c1b923 commit 6fc83b7

File tree

8 files changed

+124
-12
lines changed

8 files changed

+124
-12
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ Here's a list of supported alternative widgets for different JSONSchema data typ
104104
#### `string`:
105105

106106
* `textarea`: a `textarea` element;
107+
* `password`: an `input[type=password]` element;
107108
* by default, a regular `input[type=text]` element is used.
108109

109110
#### `number` and `integer`:

playground/samples/nested.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ module.exports = {
1010
},
1111
tasks: {
1212
type: "array",
13+
title: "Tasks",
1314
items: {
1415
type: "object",
15-
title: "Task",
1616
required: ["title"],
1717
properties: {
1818
title: {

playground/samples/simple.js

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,47 @@
11
module.exports = {
22
schema: {
3-
title: "A simple todo entry",
3+
title: "A registration form",
44
type: "object",
5-
required: ["title"],
5+
required: ["firstName", "lastName"],
66
properties: {
7-
title: {type: "string", title: "Title", default: "A new task"},
8-
done: {type: "boolean", title: "Done?", default: false}
7+
firstName: {
8+
type: "string",
9+
title: "First name",
10+
},
11+
lastName: {
12+
type: "string",
13+
title: "Last name",
14+
},
15+
age: {
16+
type: "integer",
17+
title: "Age"
18+
},
19+
bio: {
20+
type: "string",
21+
title: "Bio",
22+
},
23+
password: {
24+
type: "string",
25+
title: "Password"
26+
}
927
}
1028
},
1129
uiSchema: {
12-
done: {
13-
widget: "radio"
30+
age: {
31+
widget: "updown"
32+
},
33+
bio: {
34+
widget: "textarea"
35+
},
36+
password: {
37+
widget: "password"
1438
}
1539
},
1640
formData: {
17-
title: "My task",
18-
done: false
41+
firstName: "Chuck",
42+
lastName: "Norris",
43+
age: 75,
44+
bio: "Roundhouse kicking asses since 1940",
45+
password: "noneed",
1946
}
2047
};

playground/styles.css

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
width: 200px;
33
}
44

5-
.rjsf input[type=text], .rjsf textarea {
5+
.rjsf input[type=text],
6+
.rjsf input[type=number],
7+
.rjsf input[type=password],
8+
.rjsf input[type=range],
9+
.rjsf textarea,
10+
.rjsf select {
611
font-weight: normal;
7-
width: 350px;
12+
width: 320px;
813
}
914

1015
.rjsf textarea {

src/components/fields/ArrayField.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class ArrayField extends Component {
6363

6464
render() {
6565
const {schema, uiSchema, name} = this.props;
66-
const title = name || schema.title;
66+
const title = schema.title || name;
6767
const {items} = this.state;
6868
return (
6969
<fieldset
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React, { PropTypes } from "react";
2+
3+
4+
function PasswordWidget({
5+
schema,
6+
label,
7+
placeholder,
8+
value,
9+
defaultValue,
10+
required,
11+
onChange
12+
}) {
13+
return (
14+
<input type="password"
15+
value={value}
16+
defaultValue={defaultValue}
17+
placeholder={placeholder}
18+
required={required}
19+
onChange={(event) => onChange(event.target.value)} />
20+
);
21+
}
22+
23+
if (process.env.NODE_ENV !== "production") {
24+
PasswordWidget.propTypes = {
25+
schema: PropTypes.object.isRequired,
26+
label: PropTypes.string,
27+
placeholder: PropTypes.string,
28+
value: PropTypes.oneOfType([
29+
React.PropTypes.string,
30+
React.PropTypes.number,
31+
]),
32+
defaultValue: PropTypes.oneOfType([
33+
React.PropTypes.string,
34+
React.PropTypes.number,
35+
]),
36+
required: PropTypes.bool,
37+
onChange: PropTypes.func,
38+
};
39+
}
40+
41+
export default PasswordWidget;

src/utils.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import PasswordWidget from "./components/widgets/PasswordWidget";
12
import RadioWidget from "./components/widgets/RadioWidget";
23
import UpDownWidget from "./components/widgets/UpDownWidget";
34
import RangeWidget from "./components/widgets/RangeWidget";
@@ -33,6 +34,7 @@ export function getAlternativeWidget(type, name) {
3334
break;
3435
case "string":
3536
switch(name) {
37+
case "password": return PasswordWidget;
3638
case "radio": return RadioWidget;
3739
case "select": return SelectWidget;
3840
case "textarea": return TextareaWidget;

test/index_test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,42 @@ describe("Form", () => {
589589
expect(comp.state.formData).eql({foo: "b"});
590590
});
591591
});
592+
593+
describe("password", () => {
594+
const uiSchema = {
595+
foo: {
596+
widget: "password"
597+
}
598+
};
599+
600+
it("should accept a uiSchema object", () => {
601+
const {node} = createComponent({schema, uiSchema});
602+
603+
expect(node.querySelectorAll("[type=password]"))
604+
.to.have.length.of(1);
605+
});
606+
607+
it("should support formData", () => {
608+
const {node} = createComponent({schema, uiSchema, formData: {
609+
foo: "a"
610+
}});
611+
612+
expect(node.querySelector("[type=password]").value)
613+
.eql("a");
614+
});
615+
616+
it("should update state when text is updated is checked", () => {
617+
const {comp, node} = createComponent({schema, uiSchema, formData: {
618+
foo: "a"
619+
}});
620+
621+
Simulate.change(node.querySelector("[type=password]"), {
622+
target: {value: "b"}
623+
});
624+
625+
expect(comp.state.formData).eql({foo: "b"});
626+
});
627+
});
592628
});
593629

594630
describe("string (enum)", () => {

0 commit comments

Comments
 (0)