I have a data structure which can optionally hold a value if so I want to display it. In my example it is the field "quantity". However if it is set both blocks will be shown instead of just one. Where is the error?
{
"when": "${data.quantity === undefined}",
"type": "Text",
"text": "for ${data.price}",
"style": "textStyleDetails"
},
{
"when": "${data.quantity >= 0}",
"type": "Text",
"text": "${data.quantity}x for ${data.price}",
"style": "textStyleDetails"
},
I also tried the conditions:
data.quantity == 'undefined'
!data.quantity
(typeOf data.quantity) === 'undefined'
None of them work.
Try using ${data.quantity == null} Null is a recognized constant in the APL data binding syntax: https://developer.amazon.com/docs/alexa-presentation-language/apl-data-binding-syntax.html#null. Also the '===' operator is not supported in APL.
Related
I created a simple logic app triggered by sending a json payload and I need to retrieve a value of a property in order to use it in a condition scope.
Thanks for you help
Please use Parse Json action, please click Use sample payload to generate schema, and then paste your json to generate the schema needed to parse the json:
Then select the key of the value you want to get
===============update=============================
I defined a json string as input.
According to the json string you provided, the generated schema should look like this:
{
"properties": {
"CusttId": {
"type": "string"
},
"Direction": {
"type": "string"
},
"MyId": {
"type": "string"
},
"Reason": {
"type": "string"
},
"TestDateTime": {
"type": "string"
}
},
"type": "object"
}
I did a test and it can retrieve MyId:
Here's my json - Here I want to retrieve json content from "Property - Dynamic content". Where, dynamic content part might vary for every json request. How do I filter this by a dynamic name?
{
"Attributes":
{
"Property1": {
"Data1": {
"Value": "50"
}
},
"Property2": {
"Data2": {
"Value": "50"
}
},
"Property - Dynamic content": {
"Data3": {
"Value": "50"
},
"Data4": {
"Value": "50"
}
}
}
}
For your requirement, please refer to my logic app below:
1. I initialized a variable and store the json same with yours to simulate your situation.
2. Then use "Parse JSON".
Please notice the schema of "Parse JSON" show as:
{
"properties": {
"Attributes": {
"properties": {
"Property - Dynamic content": {
"type": [
"object",
"array"
]
},
"Property1": {
"properties": {
"Data1": {
"properties": {
"Value": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
},
"Property2": {
"properties": {
"Data2": {
"properties": {
"Value": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
},
"type": "object"
}
},
"type": "object"
}
Please pay attention to the type of Property - Dynamic content in schema above. Since the content of Property - Dynamic content is either "object" or "array", so I set both "object" and "array" as the type of Property - Dynamic content.
3. Then I initialized a variable named "result" to get the value which you want.
As we use both type "object" and "array" in the schema for Property - Dynamic content, so you may not find it in the "Dynamic content" selection. You can input its value by expression as the screenshot above. The whole expression is: body('Parse_JSON')?['Attributes']?['Property - Dynamic content']
I was able to get what I need using inline code - javascript - If anyone else is looking for the same - here it is - This will give json from Property - dynamic content element.
var data = Object.keys(workflowContext.trigger.outputs.body.Attributes);
var key = data.filter(s => s.includes('Property')).toString(); // to get element - Property - dynamic content
return workflowContext.trigger.outputs.body.Attributes[key];
I am working in ServiceNow and am trying to extend an ootb directive, then make some modifications to a couple functions. So far I've figured out how to extend the directive:
function (spModelDirective){
return angular.extend({}, spModelDirective[0], {
templateUrl:'lbl_custom_template.xml'
});
}
Within this directive, there's a function called getNestedFields that I would like to make edits to:
function getNestedFields(fields, containers) {
if (!containers)
return;
for (var _container in containers) {
var container = containers[_container];
if (container.columns) {
for (var _col in container.columns) {
var col = container.columns[_col];
for (var _field in col.fields) {
var field = col.fields[_field];
if (field.type == "container" && container.caption != "")
getNestedFields(fields, [field]);
else if (field.type == "checkbox_container")
getNestedFields(fields, field.containers);
else if (field.type == "field" || container.caption=="")
fields.push(formModel._fields[field.name]);
}
}
}
}
}
Can someone provide some guidance on what the correct syntax for this would be?
More information
Our team cloned the ootb widget-form and am trying to create a custom layout. Basically, we want each form section to be it's own tab much like the back-end form instead of one long form, which is what the ootb widget-form currently does. In the very first line of the sp-variable-layout template, it shows:
<fieldset ng-init="$last ? execItemScripts() : null" ng-show="isContainerVisible(container)" ng-repeat="container in containers">
The ng-repeat of container in containers considers each form section as a separate container (which is perfect), BUT it also considers any splits as a separate container as well. So for example, if my form's layout looks like this:
This will create two tabs: one that has every field within the begin and end splits AND a separate tab with everything after the end split. The JSON object that is created looks like this:
{
"_bootstrap_cells": 6,
"_count": 2,
"visible": true,
"columns": [{
"fields": [{
"name": "type_of_account",
"type": "field"
}, {
"name": "routing_transit_number",
"type": "field"
}]
}, {
"fields": [{
"name": "type_of_payment",
"type": "field"
}, {
"name": "check_digit",
"type": "field"
}]
}],
"caption": "Direct Deposit",
"id": "b456b9d2137ac340177c36328144b0ef",
"scope_name": "x_dnf_table"
}, {
"_bootstrap_cells": 12,
"_count": 1,
"visible": true,
"columns": [{
"fields": [{
"name": "account_number",
"type": "field"
}, {
"name": "account_title",
"type": "field"
}, {
"name": "financial_institution_name",
"type": "field"
}]
}],
"caption": "",
"id": "",
"scope_name": "x_dnf_table"
}
Notice the first "section" has a caption, but ServiceNow treats the split section as its own separate section with no caption at all.
I want to change the spModel directive to produce only containers with captions as their own tab and if a container does NOT have a caption, to append it to the previous container that does have a caption.
I don't think you can edit this function as this is hosted as a file on Servicenow. See https://hi.service-now.com/scripts/app.$sp/directive.spModel.js then just control-f for the getNestedFields.
Per this thread; https://community.servicenow.com/thread/247907#1059129 I believe spModal is just a wrapper for $uibModal.
What you can do is make your own directive on sp_angular_provider.
I have not been successful in getting the destroy strategy to work on any sibling properties or sibling objects. It only works on sibling array of objects. Please check this example:
$scope.schema = {
"type": "object",
"properties": {
"propertyOne": {
"type": "string",
"enum": ["option1", "option2"],
"title": "Property One Select"
},
"propertyTwo": {
"type": "string",
"enum": ["option3", "option4"],
"title": "Property Two Select"
},
"objectOne": {
"type": "object",
"properties": {
"objectOnePropertyThree": {
"type": "string",
"enum": ["option5","option6"],
"title": "Property Three Select"
}
}
},
"arrayOfObjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"arrayObjectPropertyFour": {
"type": "string",
"enum": ["option7","option8"],
"title": "Property Four Select"
}
}
}
}
},
"required": ["propertyOne"]
};
$scope.form = [{
"key": "propertyOne"
}, {
"key": "propertyTwo",
"condition": "model.propertyOne === \"option1\""
},{
"key": "objectOne.objectOnePropertyThree",
"condition": "model.propertyOne === \"option1\""
},{
"key": "arrayOfObjects",
"condition": "model.propertyOne === \"option1\""
},
{
"type": "submit",
"title": "Save"
}];
http://jsfiddle.net/mutharasus/dp18a70b/
In here if you select the first dropdown to "Option1" then select all the other dropdowns and save. Then go back and switch the first dropdown to "Option2" and save you can see that only the very last array of objects is removed with the destroy strategy.
Am I doing something wrong or is this a bug in angular-schema-form? I looked under the issues that are currently open in the github project and I do not see an open issue about this.
You're correct, it's not currently behaving the way that you expect when an individual field is removed from the view because of a condition.
Here's what's happening: under the "old" bundled decorators for ASF, each field-type decorator is rendered on the page within an outer tag. The contents of the appropriate field template are then processed and rendered. Condition logic applies to everything within the tag, but not to the tag itself. Normally, this would be fine, but the destroyStrategy logic was assigned to the $destroy event of the tag. The end result is that the $destroy event will never fire unless the entire tag would be removed from the DOM. This is why the model values in the array of objects are being cleaned up - the container is removed when the "model.propertyOne === 'option1'" condition fails, which cascades the $destroy event to each object in the array.
I think that this got overlooked with the creation and release of the new builder, because I raised the issue at the end of the PR for the feature (https://github.com/Textalk/angular-schema-form/pull/371).
On the bright side, the new builder approach (which you can use by adding the bootstrap-decorator file from https://github.com/Textalk/angular-schema-form-bootstrap) doesn't have this issue. Instead, the destroyStrategy logic is applied via directive to the form fields because the tag is no longer used. Unless you have a need to stay with the old decorators at this time, I suggest grabbing the new ones and giving them a try.
Let us know how it goes!
I'm writing a simple JSON schema and using minItems to validate the number of items in a given array. My schema is as follows:
{
"title": "My Schema",
"type": "object",
"properties": {
"root": {
"type": "array",
"properties": {
"id": {
"type": "string"
},
"myarray": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 4,
"uniqueItems": true
},
"boolean": {
"type": "boolean"
}
},
"required": ["id","myarray","boolean"]
}
},
"required": [
"root"
],
"additionalProperties": false
}
Now I would expect the following JSON to fail validation given the element myarray has nothing in it. But when using this online validator, it passes. Have I done something wrong or is the schema validator I'm using faulty?
{
"root":[
{
"id":"1234567890",
"myarray":[],
"boolean":true
}
]
}
I am not sure why or what it is called, but the correct schema definition for your requirement should be as shown further down.
From what I understand from the JSON Schema definitions, you should declare the properties of an array inside the items declaration. In your schema you where defining properties outside of the array item declaration.
In your schema you have the two different types of array declaration:
Once with just a single object (a string for the "myarray" object)
Once with a complex object (the object name "myComplexType" in the code below)
Have a look at the definitions of both, how they are structured and how they would be interpreted.
The corrected schema:
{
"title": "My Schema",
"type": "object",
"properties": {
"root": {
"type": "array",
"items": { <-- Difference here - "items" instead of "properties"
"type": "object", <-- here - define the array items as a complex object
"title": "myComplexType", <-- here - named for easier referencing
"properties": { <-- and here - now we can define the actual properties of the object
"id": {
"type": "string"
},
"myarray": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 4,
"uniqueItems": true
},
"boolean": {
"type": "boolean"
}
}
},
"required": [
"id",
"myarray",
"boolean"
]
}
},
"required": [
"root"
],
"additionalProperties": false
}
Remove the comments I added with <-- when copying over to your code, added for pointing where there changes are.
As a note, I do however don't understand why the validator didn't give an error for the 'malformed' schema, but might just be that it saw the definition as you had it as additional properties, not entirely sure.
The only thing wrong with your schema is that the root property should have type object instead of array. Because the properties keyword is not defined for arrays, it is ignored. Therefore, the part of the schema you were trying to test was completely ignored even though it was correct.
Here is the relevant passage from the specification
Some validation keywords only apply to one or more primitive types. When the primitive type of the instance cannot be validated by a given keyword, validation for this keyword and instance SHOULD succeed.
http://json-schema.org/latest/json-schema-validation.html#rfc.section.4.1