I'm working on creating my own schematics. This schematics will be responsible for creating a component (container) with some code. Template of this component will contain a few other components. One of this component will be banner component that will be optional. This banner will display text that will be translated into other languages, so I also should ask the user to provide (default) translation text if the banner will be included in the component.
Here is an example of this template:
name#dasherize.component.html.template:
<% if (includeBanner) { %>
<app-banner [title]="'<%= translationModuleKey %>.banner.title' | translate"
[description]="'<%= translationModuleKey %>.banner.description' | translate">
</app-banner>
<% } %>
<app-other-component>
</app-other-component>
Here is my schema.json:
{
"$schema": "http://json-schema.org/schema",
"id": "MySchematics",
"title": "My schematics",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the container",
"x-prompt": "Container name"
},
"includeBanner": {
"type": "boolean",
"description": "Include banner",
"default": "true",
"x-prompt": "Include banner"
},
"bannerTitle": {
"type": "string",
"description": "Banner title",
"x-prompt": "Banner title"
},
"bannerDescription": {
"type": "string",
"description": "Banner description",
"x-prompt": "Banner description"
},
"translationModuleKey": {
"type": "string",
"description": "Root key for translations"
}
},
"required": [
"name", "includeBanner", "bannerTitle", "bannerDescription"
]
}
My problem is that when user will set includeBanner to true, fields bannerTitle and bannerDescription should be required and there should be displayed prompt if those properties were not provided, but if includeBanner will be false, bannerTitle and bannerDescription shouldn't be required and there shouldn't be displayed prompt to fill these properties if those properties were not provided.
Any idea how to achieve that?
I was struggling with the same problem. What I've discovered - if you need conditional prompts, then you can't rely on declarative schema.json file (it doesn't support conditions).
Instead, you should use the askConfirmation function from #angular/cli/utilities/prompt.
So your example could look like this:
import { askConfirmation } from '#angular/cli/utilities/prompt';
export function yourSchematicsFn(options: Schema): Rule {
return async (tree: Tree, context: SchematicContext) => {
const includeBanner = await askConfirmation('Include Banner?', true);
if(includeBanner) {
// ask for bannerTitle and bannerDescription
}
else {
// do something else
}
return chain(/* chain your rules here */);
}
}
I've discovered this in Angular CLI ng-add schematics source code: askConfirmation.
Related
I need to do the complex schema validation, which has multiple $ref in it. I am using jsonschema npm package to achieve it.
Example:
Parent Schema : - parent.json id: https://example.com/ww/ee/parent.json $ref:
sample.json#/definitions/event
Child Schema: - child.json id: https://example.com/ww/ee/child.json Child has event properties in
it.
I have placed these 2 json files in local folder called schemas. Now the issue is, i am trying to add reference child schema. But i am getting following error,
stack: "SchemaError: no such schema https://example.com/ww/ee/child.json#/definitions/event\n
at Validator.resolve (http://localhost:3000/static/js/bundle.js:18810:11)\n
at Validator.validateSchema (http://localhost:3000/static/js/bundle.js:18724:25)\n
at Validator.validateProperties (http://localhost:3000/static/js/bundle.js:17209:20)\n
at Validator.validateSchema (http://localhost:3000/static/js/bundle.js:18737:34)\n
at Validator.validateSchema (http://localhost:3000/static/js/bundle.js:18726:17)\n
at Validator.validate (http://localhost:3000/static/js/bundle.js:18654:21)\n
at module.exports.validate (http://localhost:3000/static/js/bundle.js:18393:12)\n
at filterNotification (http://localhost:3000/static/js/bundle.js:1143:25)\n
at async Function.startSendData (http://localhost:3000/static/js/bundle.js:1026:30)"
[[Prototype]]: Error
const schema = require('../schemas/parentschema.json')
const eventSchema = require('../schemas/childSchema.json')
const validator = new Validator();
validator.addSchema(eventSchema, 'https://example.com/ww/ee/childSchema.json')
const isValidSchema = validator.validate(JsonObjectTovalidate, schema)
Parent schema:
"$ref": "#/definitions/noify",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://example.com/ww/ee/parentschema.json",
"description": "Sample",
"definitions": {
"noify": {
"description": "sample",
"properties": {
"events": {
"description": "sample",
"items": {
"$ref": "childSchema.json#/definitions/event"
},
"type": "array",
"maxItems": 250
},
},
"title": "testing",
"type": "object",
"additionalProperties": false
}
},
}
Child Schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"version": "1.4.0",
"description": "Promoting",
"id": "https://example.com/ww/ee/childSchema.json",
"$ref": "#/definitions/event",
"definitions": {
"event": {
"properties": {
"dateTime": {
"$ref": "otherSchema.json#/definitions/dateTime",
"description": "Originator datetime when the event actually occured"
},
"additionalProperties": false
},
},
}
In the child schema, if I remove this line, "$ref": "#/definitions/event", then it is working fine. Why is that so? without removing how can i make it to work?
In draft4 of JSON Schema, $ref cannot exist side-by-side with any other keyword. However, it doesn't look like you require that $ref to be there in your childSchema.json document - you reference this document as "childSchema.json#/definitions/event", not simply "childSchema.json", so it should be fine to remove.
Alternatively you can move the definition in childSchema.json to the top level (remove the "definitions" and "event" keywords entirely, moving the schema up two levels to the base of the document) and remove the $ref in that file, and refer to it as "$ref": "childSchema.json".
Hi I'm using the Adaptive card SDK in a web page, using a Sample Card like this:
var card = {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "TextBlock",
"text": "Present a form and submit it back to the originator"
},
{
"type": "Input.Text",
"id": "firstName",
"placeholder": "What is your first name?"
},
{
"type": "Input.Text",
"id": "lastName",
"placeholder": "What is your last name?"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Action.Submit"
}
]};
and rendering using the usual rubric. I'd like to get the inputs back with the submit so I tried this
// Set the adaptive card's event handlers. onExecuteAction is invoked
// whenever an action is clicked in the card
adaptiveCard.onExecuteAction = function (action) { console.log(action.toJSON()) }
which just gives me:
Object title: "Action.Submit" type: "Action.Submit" __proto__: Object
How do I get the values of the input fields on the submit action?
TIA for any comments, advice and answers
You can use the data property of the action object just like this:
adaptiveCard.onExecuteAction = function (action) {
alert(`Hello ${action.data.firstName} ${action.data.lastName}`);
}
Here's a full jsfiddle.
There are many other interesting properties on the action object, but I haven't found good documentation.
However, the source code of the adaptive card visualizer contains some usage examples.
I have an Alpaca JS form comprised of an array of items which each consist of a textbox and a checkbox. For some reason, when I change the order using the dynamic controls, it successfully renumbers the textbox but doesn't change the number of the checkbox. This also results in a duplicate name assigned if the same top button to dynamically add new fields is pressed. The end result is incorrect data being passed when the form is submitted. How can I fix this to properly renumber the checkboxes?
Here's a sample of the Alpaca configuration:
$("#form1").alpaca({
"schema": {
"title": "Testing checkbox array IDs",
"description": "Testbox checkbox array test.",
"type": "object",
"properties": {
"form-fields": {
"title": "Fields",
"description": "These are the fields.",
"type": "array",
"items": {
"type": "object",
"properties": {
"field-name": {
"type": "string",
"title": "Field Name",
"description": "Enter the name for this field.",
"required": true
},
"field-box": {
"type": "boolean",
"title": "Field Box",
"description": "Check this box.",
"default": false
}
}
}
}
}
}
});
I couldn't find a way to correct the behavior itself but I was able to work around it by adding a postRender event to the Alpaca definition as follows:
"postRender": function(control) {
control.childrenByPropertyId["form-fields"].on("move", function() { $('input[type=checkbox]').each(function(index) { $(this).attr("name", $(this).closest("div:has(*[name])").first().attr("name")) }); });
control.childrenByPropertyId["form-fields"].on("add", function() { $('input[type=checkbox]').each(function(index) { $(this).attr("name", $(this).closest("div:has(*[name])").first().attr("name")) }); });
control.childrenByPropertyId["form-fields"].on("remove", function() { $('input[type=checkbox]').each(function(index) { $(this).attr("name", $(this).closest("div:has(*[name])").first().attr("name")) }); });
}
This is a bit of a hack but it works because the parent object does get assigned the correct name value and the form will post with those values if the name is just copied down into the input elements.
I have html that is dynamically generated from JSON and I would like to implement some validation logic.
To clarify, here is an example:
<div ng-switch on="field.type" ng-hide="{{ field.hide }}">
<div ng-switch-when="input" class= "col-md-6" ng-class="{'has-error': reqField(field.name, entity[field.name]) }">
<input
ng-model="entity[field.name]" id="{{field.name}}" class="form-control"
type="text" ng-style="setStyle(field.style)" ng-change="{{field.change}}" />
</div>
</div>
{
"title": "Json Title",
"id": "j_id",
"groupfields": [
{
"name": "jsonname",
"title": "JSON Title",
"type": "jsonselect",
"namevalue": "jsonvalue",
"combo": "jsondropdown",
"change" : "jsonChanged()"
},
{
"name": "jsonEmail",
"title": "JSON Email Address",
"type": "display"
},
{
"name": "jsonPhone",
"title": "JSON Phone Number",
"type": "display"
}
]
}, {
"title": "Json Title",
"id": "j_id",
"groupfields": [
{
"name": "jsonname",
"title": "JSON Title",
"type": "jsonselect",
"namevalue": "jsonvalue",
"combo": "jsondropdown",
"change" : "jsonChanged()"
},
{
"name": "jsonEmail",
"title": "JSON Email Address",
"type": "display"
},
{
"name": "jsonPhone",
"title": "JSON Phone Number",
"type": "display"
}
]
},
if (entityName) {
return false;
} else {
return true;
}
So for clarification, ex: 'field.type' in the ng-switch on is the "type" in the JSON - and we can determine which html div to display the content based on different JSON keys/values.
This implies that one html div could potentially be used to generate hundreds of input fields so this needs to be dynamic.
I would like to add validation for when a required field is empty. At the moment, I've tried adding the ng-class="{has-error': } which points to my function reqField. However, because this function is getting fired for EVERY field with "type": jsonselect, this function is checking whether or not the field is empty - which is really inefficient in terms of speed and usability (super laggy).
The javascript you see above is more or less the logic that the function reqField() does in order to check whether or not the field is empty (very inefficient since we're checking hundreds).
What I would like to use is something along the lines of ng-required={{field.required}} and make a new key/value in the JSON to determine whether or not I want this field to be a required field (sort like this):
{
"title": "Json Title",
"id": "j_id",
"groupfields": [
{
"name": "jsonname",
"title": "JSON Title",
"type": "jsonselect",
"namevalue": "jsonvalue",
"combo": "jsondropdown",
"change" : "jsonChanged()"
},
{
"name": "jsonEmail",
"title": "JSON Email Address",
"type": "display",
"required": true
},
{
"name": "jsonPhone",
"title": "JSON Phone Number",
"type": "display",
"required": true
}
]
},
~ and somehow pass that information to the ng-class="{has-error': } so that we can highlight - or do whatever we want once we know the field has been filled in/or is empty.
Form validation is built in to AngularJS. The ng-required directive will add error state to the form object, so that you can set up your ng-class like so:
<div ng-switch-when="input" class= "col-md-6" ng-class="{'has-error': myForm[field.name].$error.required }">
Your form and input must have name attributes for this to work:
<form name="myForm">
...
<input name="{{field.name}}" ng-required="field.required">
Is there a way to replace the Star symbol with an asterisk on a 'required' field label on Alpaca?
Here is the schema:
var Schema = {
"title": "Lista controlli",
"type": "array",
"items": {
"type": "object",
"title": "Controllo Lavorazione",
"properties": {
...
"Nome": {
"title": "Nome",
"type": "string",
"required": true
}
}
}
}
Thanks in advance.
You can deal with that using css like this:
.alpaca-icon-required::before {
content: "*"
}
You could also change it's font-size because it will be kinda big.
Hope this works for you. I this isn't what you're looking for don't hesitate to comment.
In the latest version, 1.5.24, the star preceding the field label has been replaced with the text '(required)' following the field label.