I have a schema here where I would like to have a drop down, to select an option, and from there - depending on the selection different options appear; all being nested within an array to have multiples of them.
I have noticed that when I am filling in with dummy data, the output json isnt storing the name of the selected option
so the data.json looks something like this:
{
"page1": [
{
"imageOptions": {
"imageHeightType": "vh",
"imageHeight": 50
},
"textboxArea": {
"headerText": "Header for selection1",
"headingTag": "h1",
"textBoxOpacity": 15
}
},
{
"content": "This is a complety different selection, yet there is no name to tell the difference between these two difference objects"
}
]
}
As you can see theres no object to wrap these two different items within the page1 array - Ideally would like something like:
{
"page1": [
{
// Title of object goes here from schema
"imageOptions": {
"imageHeightType": "vh",
"imageHeight": 50
},
"textboxArea": {
"headerText": "Header for selection1",
"headingTag": "h1",
"textBoxOpacity": 15
}
},
{
// Title of object goes here from schema
"content": "This is a completely different selection, yet there is no name to tell the difference between these two difference objects"
}
]
}
Is there a way to make this so? I have looked on the docs for AnyOf but not much luck. Quite new to React-JsonSchema-Forms.
Below is my current Schema:
{
"type": "object",
"properties": {
"page1": {
"type": "array",
"items": {
"type": "object",
"anyOf": [
{
"title": "Full Width Image",
"type": "object",
"properties": {
"imageOptions": {
"type": "object",
"title": "Image",
"properties": {
"image": {
"type": "string",
"title": "Image",
"format": "data-url"
},
"imageHeightType": {
"enum": [
"px",
"vh"
]
},
"imageHeight": {
"type": "number",
"title": "Image Height"
}
}
},
"textboxArea": {
"type": "object",
"title": "Textbox Area",
"properties": {
"headerText": {
"type": "string",
"title": "Heading Text"
},
"headingTag": {
"enum": [
"h1",
"h2",
"h3"
]
},
"imageText": {
"type": "string",
"title": "Body Text"
},
"textboxPosition": {
"title": "Textbox Position",
"enum": [
"Left",
"Center",
"Right"
]
},
"textboxColor": {
"title": "Color of Textbox Area",
"type": "string"
},
"textBoxOpacity": {
"title": "Textbox Opacity %",
"type": "integer",
"minimum": 0,
"maximum": 100,
"multipleOf": 5
}
}
}
}
},
{
"title": "Custom Block",
"type": "object",
"properties": {
"content": {
"type": "string"
}
}
}
]
}
}
}
}
Also Link to the online schema editor if it helps understand my issue
Why not just add a name-like property to each object? You can then hide/disable it if you want:
schema:
"anyOf": [
{
"title": "Full Width Image",
"type": "object",
"properties": {
"name": {
"type": "string",
"default": "fullWidthImage"
},
"imageOptions": {
"type": "object",
"title": "Image",
"properties": {...}
...
}
...
}
},
{
"title": "Custom Block",
"type": "object",
"properties": {
"name": {
"type": "string",
"default": "custom"
},
"content": {
"type": "string"
}
}
}
]
uiSchema:
{
"page1": {
"items": {
"name": {
"ui:widget": "hidden"
},
"imageOptions": {...},
...
}
}
formData then should look like this:
{
"page1": [
{
"name": "fullWidthImage",
"imageOptions": {
"imageHeightType": "vh",
"imageHeight": 50
},
"textboxArea": {
"headerText": "Header for selection1",
"headingTag": "h1",
"textBoxOpacity": 15
}
},
{
"name": "custom",
"content": "This is a complety different selection, yet there is no name to tell the difference between these two difference objects"
}
]
}
Related
I have this schema:
{
"type": "object",
"title": "Comment",
"required": [
"comments"
],
"properties": {
"comments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"email": {
"title": "Email",
"type": "string",
"pattern": "^\\S+#\\S+$",
"description": "Email will be used for evil."
},
"spam": {
"title": "Spam",
"type": "boolean",
"default": true
},
"comment": {
"title": "Comment",
"type": "string",
"maxLength": 20,
"validationMessage": "Don't be greedy!"
}
},
"required": [
"name",
"comment"
]
}
}
}
}
This is an array of comments. I can add and remove comments.
How can I render 2 items of the array always by default ?
I've tried with maxItems and minItems but those parameters don't render items.
There are two ways to do it currently.
First is to set them in the default model so it looks something like:
$scope.model = {
"comments": [{},{}]
}
The second would be to use onChange on the array:
"onChange": function(val) { if(val.length < 2) val.push({}); }
The difference between the two being that the onChange will not allow it to drop below the minimum length you set while the first option is just for the initial default.
I've got a JSON Schema that looks like this:
{
"required": [
"instructions"
],
"properties": {
"instructions": {
"title": "Instructions",
"minItems": 3,
"type": "array",
"items": {
"required": [
"typeId",
"teamId",
"disciplineId"
],
"properties": {
"typeId": {
"minimum": 1,
"title": "Appointment Type",
"type": "integer"
},
"teamId": {
"minimum": 1,
"title": "Team",
"type": "integer"
},
"disciplineId": {
"minimum": 1,
"title": "Discipline",
"type": "integer"
},
"prefClinicianId": {
"title": "Pref. Clinician",
"anyOf": [
{
"type": "null"
},
{
"minimum": 1,
"type": "integer"
}
]
},
"prefTime": {
"title": "Pref. Time",
"anyOf": [
{
"type": "null"
},
{
"type": "integer"
}
]
},
"childRequired": {
"title": "Child Req'd",
"type": "boolean"
}
},
"type": "object"
}
}
},
"type": "object"
}
As you can see, I've added titles to all the properties. However, the error object I get back looks like:
[
{
"keyword": "minItems",
"dataPath": ".instructions",
"schemaPath": "#/properties/instructions/minItems",
"params": {
"limit": 3
},
"message": "should NOT have less than 3 items"
},
{
"keyword": "type",
"dataPath": ".instructions[0].typeId",
"schemaPath": "#/properties/instructions/items/properties/typeId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
},
{
"keyword": "type",
"dataPath": ".instructions[0].teamId",
"schemaPath": "#/properties/instructions/items/properties/teamId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
},
{
"keyword": "type",
"dataPath": ".instructions[0].disciplineId",
"schemaPath": "#/properties/instructions/items/properties/disciplineId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
}
]
As you can see, the title is not in there. How can I get the titles with the errors?
Please note that this question is specific to AJV.
When you create your AJV object set the verbose option to true.
This will add a parentSchema property to the ajv error with the original schema. It will also add a schema property that contains the specific schema attribute that caused the validation failure.
Here's an example:
var ajv = new Ajv({
$data: true,
verbose: true
});
let schema = {
title: 'object title',
type: 'object',
properties: {
str: {
title: "A string property",
type: "string"
}
}
};
let data = {
str: 3
};
ajv.validate(schema, data)
console.log('ERRORS: ', this.ajv.errors)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/5.3.0/ajv.bundle.js"></script>
Given this JSON object:
{
"objects": {
"foo": {
"id": 1,
"name": "Foo"
},
"bar": {
"id": 2,
"name": "Bar"
}
}
}
This is an object containing sub objects where each sub object has the same structure - they're all the same type. Each sub-object is keyed uniquely, so it acts like a named array.
I want to validate that each object within the objects property validates against a JSON Schema reference.
If the objects property was an array, such as:
{
"objects": [
{
"id": 1,
"name": "Foo"
},
{
"id": 2,
"name": "Bar"
}
]
}
I could validate this with a schema definition such as:
{
"id": "my-schema",
"required": [
"objects"
],
"properties": {
"objects": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
}
}
}
}
}
This is achieved because the type is array, and this permits the validation of items.
Is it possible to do something similar, but with nested objects?
Thanks!
You can try something like this:
{
"id": "my-schema",
"type": "object",
"properties": {
"objects": {
"type": "object",
"patternProperties": {
"[a-z]+": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"id",
"name"
]
}
}
}
}
}
The above answer works for restricting the object property names to lower-case letters. If you do not need to restrict the property names, then this is simpler:
{
"id": "my-schema",
"type": "object",
"properties": {
"objects": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string }
}
},
"required": [
"id",
"name"
]
}
}
}
}
I omitted the inner "additionalProperties": false from the above answer because I find that using that keyword causes more problems than it solves, but it is a valid use of the keyword if you want validation to fail on the inner objects if they have properties other than "name" and "id".
I don't know if I'm just blind or something but how can I do the following:
I have a User model with a hasOne relation to a UserData model. I only want one property of UserData directly in the results of User.
The relation in User looks like this:
"relations": {
"userData": {
"type": "hasOne",
"model": "UserData"
}
}
And the default scope in User:
"scope": {
"include": "userData"
}
So the result for one User is:
[
{
"id": 5,
"email": "example#example.com",
"name": "Example",
"userData": {
"id": 5,
"birthdate": "1971-09-06T00:00:00.000Z"
}
}
]
But what I want is this:
[
{
"id": 5,
"email": "example#example.com",
"name": "Example",
"birthdate": "1971-09-06T00:00:00.000Z"
}
]
How can I achive this?
Edit:
The two model definitions:
ChiliUser:
{
"name": "ChiliUser",
"base": "ChiliUserData",
"idInjection": true,
"options": {
"validateUpsert": true,
"mysql": {
"table": "person"
}
},
"properties": {
"id": {
"type": "number"
},
"email": {
"type": "string"
},
"password": {
"type": "string"
},
"vorname": {
"type": "string"
},
"name": {
"type": "string"
},
"spitzname": {
"type": "string"
},
"strasse": {
"type": "string"
},
"plz": {
"type": "number"
},
"ort": {
"type": "string"
},
"geolat": {
"type": "string"
},
"geolng": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
ChiliUserData:
{
"name": "ChiliUserData",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true,
"mysql": {
"table": "person_data"
}
},
"properties": {
"id": {
"type": "number"
},
"person_id": {
"type": "number"
},
"birthdate": {
"type": "date"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
Are you using the built-in User model? If you are, you can simply extend it with your UserData model using base: "User", and the underlying schema will be as you desire:
{
"name": "UserData",
"base": "User",
"properties": {}
...
}
But this setup would mean you'd use UserData over User in your code. Since the built-in User model gets in the way, I'd recommend a different word like Person or Customer, in which case it would look like:
{
"name": "Person",
"base": "User",
"properties": {
...extra user data properties only...
}
...
}
This way, only Person will have all the extra "user data" fields on it, but will also include all the fields/methods defined for User inside node_modules/loopback/common/models/User.json. If you're using MySQL, the Person table will be created with the combination of fields from both User and Person.
i have used $.getJSON for getting json data on pagebeforeshow but it is not working as it have to.
$(document).on('pagebeforeshow', '#inpGrid', function(e) {
alert("inpGrid");
var tat_url = "http://192.168./html5/Demo/json/list.json";
var url = "http://api.openweathermap.org/data/2.5/forecast?lat=35&lon=139&callback=?" ;
$.getJSON(tat_url, function(res) {
console.log(res)
});
});
the code is as above, when using url in $.getJSON it is working, wheras as using tat_url it is not working.
the http://192.168./html5/Demo/json/list.json consists as follows
{
"response": {
"respCode": 0,
"output": {
"delAction": "OP",
"delTmplt": "sibcVizEdit",
"title": "List TATs",
"layout": "grid",
"srvObjRef": "iawme1/IAWMblztnExpert-ListSIBCs_MB1412577249595",
"startIndex": "0",
"recsPerPage": "18",
"noPages": "1",
"curPageNo": "1",
"fieldInfo": [
{
"label": "Name",
"type": "STRING"
}
{
"label": "Alias",
"type": "STRING"
}
{
"label": "Datatype",
"type": "STRING"
}
{
"label": "Default Value",
"type": "STRING"
}
{
"label": "Visibility",
"type": "STRING"
}
],
"records": [
{
"Name": "psngrType"
"Alias": "Pasngr Type"
"Datatype": "STRING"
"Default Value":"CC"
"Visibility": "0"
},
{
"Name": "flightNo"
"Alias": "Flight No"
"Datatype": "STRING"
"Default Value":"$RV_flightNo"
"Visibility": "0"
}
],
"relServices": {
"AServices": [
{
"ref": "IAWMblztnExpert-ListSIBCs-UpdateBizContext_MB",
"title": "Update SIBC",
"desc": "",
"srvRef": "IAWMblztnExpert-ListSIBCs-UpdateBizContext_MB",
"slctdOffsets": "0"
},
{
"ref": "IAWMblztnExpert-ListSIBCs-ListIICsInSIBC_MB",
"title": "List IICs",
"desc": "",
"srvRef": "IAWMblztnExpert-ListSIBCs-ListIICsInSIBC_MB",
"slctdOffsets": "0"
},
{
"ref": "IAWMblztnExpert-ListSIBCs-Deploy SIBC_MB",
"title": "Deploy",
"desc": "",
"srvRef": "IAWMblztnExpert-ListSIBCs-Deploy SIBC_MB",
"slctdOffsets": "0"
}
]
}
}
}
}
Can someone help me please thanks.
Your JSON contain syntax errors, look your ''fieldInfo'' node. You didn't seperate your differents object by ,
Example:
{
"label": "Name",
"type": "STRING"
},
{
"label": "Alias",
"type": "STRING"
}
instead of
{
"label": "Name",
"type": "STRING"
}
{
"label": "Alias",
"type": "STRING"
}
Use online JSON validator if you need check rest of your json file easily : http://jsonlint.com/