Skip to content
This repository has been archived by the owner on Dec 31, 2020. It is now read-only.

Commit

Permalink
Support readOnly property from latest validation draft (rjsf-team#1282
Browse files Browse the repository at this point in the history
)

* Support `readOnly` property from draft-handrews-json-schema-validation-01

* Fix failing test

* Add note in docs about using the readOnly property

* Update to be consistent with the changes done in commit 497620f
  • Loading branch information
pahen authored and epicfaace committed May 14, 2019
1 parent 1ee343d commit 98952b7
Show file tree
Hide file tree
Showing 4 changed files with 294 additions and 1 deletion.
14 changes: 14 additions & 0 deletions docs/form-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,20 @@ The `ui:disabled` uiSchema directive will disable all child widgets from a given

The `ui:readonly` uiSchema directive will mark all child widgets from a given field as read-only.

You can also set specific fields to read-only by setting the `readOnly` property in the schema.

```js
const schema = {
type: "object",
properties: {
foo: {
type: "string",
readOnly: true
}
}
};
```

> Note: If you're wondering about the difference between a `disabled` field and a `readonly` one: Marking a field as read-only will render it greyed out, but its text value will be selectable. Disabling it will prevent its value to be selected at all.
#### Hidden widgets
Expand Down
6 changes: 6 additions & 0 deletions playground/samples/widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ module.exports = {
title: "A readonly field",
default: "I am read-only.",
},
readonly2: {
type: "string",
title: "Another readonly field",
default: "I am also read-only.",
readOnly: true,
},
widgetOptions: {
title: "Custom widget with options",
type: "string",
Expand Down
7 changes: 6 additions & 1 deletion src/components/fields/SchemaField.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,12 @@ function SchemaFieldRender(props) {
const FieldComponent = getFieldComponent(schema, uiSchema, idSchema, fields);
const { DescriptionField } = fields;
const disabled = Boolean(props.disabled || uiSchema["ui:disabled"]);
const readonly = Boolean(props.readonly || uiSchema["ui:readonly"]);
const readonly = Boolean(
props.readonly ||
uiSchema["ui:readonly"] ||
props.schema.readOnly ||
schema.readOnly
);
const autofocus = Boolean(props.autofocus || uiSchema["ui:autofocus"]);
if (Object.keys(schema).length === 0) {
return null;
Expand Down
268 changes: 268 additions & 0 deletions test/uiSchema_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2376,4 +2376,272 @@ describe("uiSchema", () => {
});
});
});

describe("Readonly in schema", () => {
describe("Fields", () => {
describe("ArrayField", () => {
let node;

beforeEach(() => {
const schema = {
type: "array",
items: {
type: "string",
},
readOnly: true,
};
const uiSchema = {};
const formData = ["a", "b"];

let rendered = createFormComponent({ schema, uiSchema, formData });
node = rendered.node;
});

it("should mark as readonly an ArrayField", () => {
const disabled = [].map.call(
node.querySelectorAll("[type=text]"),
node => node.hasAttribute("readonly")
);
expect(disabled).eql([true, true]);
});

it("should disable the Add button", () => {
expect(node.querySelector(".array-item-add button").disabled).eql(
true
);
});

it("should disable the Delete button", () => {
expect(node.querySelector(".array-item-remove").disabled).eql(true);
});
});

describe("ObjectField", () => {
let node;

beforeEach(() => {
const schema = {
type: "object",
properties: {
foo: {
type: "string",
},
bar: {
type: "string",
},
},
readOnly: true,
};
const uiSchema = {};

let rendered = createFormComponent({ schema, uiSchema });
node = rendered.node;
});

it("should mark as readonly an ObjectField", () => {
const disabled = [].map.call(
node.querySelectorAll("[type=text]"),
node => node.hasAttribute("readonly")
);
expect(disabled).eql([true, true]);
});
});
});

describe("Widgets", () => {
function shouldBeReadonly(selector, schema, uiSchema) {
const { node } = createFormComponent({ schema, uiSchema });
expect(node.querySelector(selector).hasAttribute("readonly")).eql(true);
}
function shouldBeDisabled(selector, schema, uiSchema) {
const { node } = createFormComponent({ schema, uiSchema });
expect(node.querySelector(selector).disabled).eql(true);
}

it("should mark as readonly a text widget", () => {
shouldBeReadonly(
"input[type=text]",
{
type: "string",
readOnly: true,
},
{}
);
});

it("should mark as readonly a file widget", () => {
// We mark a file widget as readonly by disabling it.
const { node } = createFormComponent({
schema: {
type: "string",
format: "data-url",
readOnly: true,
},
uiSchema: {},
});
expect(
node.querySelector("input[type=file]").hasAttribute("disabled")
).eql(true);
});

it("should mark as readonly a textarea widget", () => {
shouldBeReadonly(
"textarea",
{
type: "string",
readOnly: true,
},
{
"ui:widget": "textarea",
}
);
});

it("should mark as readonly a number text widget", () => {
shouldBeReadonly(
"input[type=number]",
{
type: "number",
readOnly: true,
},
{}
);
});

it("should mark as readonly a number widget", () => {
shouldBeReadonly(
"input[type=number]",
{
type: "number",
readOnly: true,
},
{
"ui:widget": "updown",
}
);
});

it("should mark as readonly a range widget", () => {
shouldBeReadonly(
"input[type=range]",
{
type: "number",
readOnly: true,
},
{
"ui:widget": "range",
}
);
});

it("should mark readonly as disabled on a select widget", () => {
shouldBeDisabled(
"select",
{
type: "string",
enum: ["a", "b"],
readOnly: true,
},
{}
);
});

it("should mark as readonly a color widget", () => {
shouldBeReadonly(
"input[type=color]",
{
type: "string",
format: "color",
readOnly: true,
},
{}
);
});

it("should mark as readonly a password widget", () => {
shouldBeReadonly(
"input[type=password]",
{
type: "string",
readOnly: true,
},
{
"ui:widget": "password",
}
);
});

it("should mark as readonly a url widget", () => {
shouldBeReadonly(
"input[type=url]",
{
type: "string",
format: "uri",
readOnly: true,
},
{}
);
});

it("should mark as readonly an email widget", () => {
shouldBeReadonly("input[type=email]", {
type: "string",
format: "email",
readOnly: true,
});
});

it("should mark as readonly a date widget", () => {
shouldBeReadonly("input[type=date]", {
type: "string",
format: "date",
readOnly: true,
});
});

it("should mark as readonly a datetime widget", () => {
shouldBeReadonly("input[type=datetime-local]", {
type: "string",
format: "date-time",
readOnly: true,
});
});

it("should mark readonly as disabled on an alternative date widget", () => {
const { node } = createFormComponent({
schema: {
type: "string",
format: "date",
readOnly: true,
},
uiSchema: {
"ui:widget": "alt-date",
},
});

const readonly = [].map.call(node.querySelectorAll("select"), node =>
node.hasAttribute("disabled")
);
expect(readonly).eql([true, true, true]);
});

it("should mark readonly as disabled on an alternative datetime widget", () => {
const { node } = createFormComponent({
schema: {
type: "string",
format: "date-time",
readOnly: true,
},
uiSchema: {
"ui:widget": "alt-datetime",
},
});

const readonly = [].map.call(node.querySelectorAll("select"), node =>
node.hasAttribute("disabled")
);
expect(readonly).eql([true, true, true, true, true, true]);
});
});
});
});

0 comments on commit 98952b7

Please sign in to comment.