I am using angular-formly to create input screens and all works great as long as I have a KEY for each VALUE.
But i have a situation where the value is an object with an array in it . It is an industry standard so I can not change the
field structure.
The parent Key is GEOCODE its value is COORDINATES (which is an array with 2 elements)
I want to edit those 2 elements (longitude and Latitude). Is this doable or does formly need a KEY:VALUE to create and input which will allow editing of those values.
/* -- JSON DATA -- */
[
"fullname": "Glen Benson",
/* this is the objext I am trying to edit coordinates elements */
**
"geolocation": {
"coordinates": [
-94.467136,
39.090707
],
"type": "Point"
}
**
]
/* -- FORMLY CONTROLLER SNIPPET --*/
{
"key": "fullname",
"type": "input",
"templateOptions": {
"type": "text",
"placeholder": "fullname"
}
},
**{
"key": "geocode.coordinates[0]",
"type": "input",
"templateOptions": {
"type": "text",
"placeholder": "geocode"
}
}**
You can get the value without having to name it some crazy thing. It should work how you have it, but I mean, my God, that is ugly.
just set the defaultValue to the value of geolocation....
key: 'CoordinateX',
defaultValue: 'model.geocode.geolocation.coordinates[0]'
OR add a controller on it to get it
key: 'CoordinateX',
controller: function($scope) {
$scope.model.CoordinateX = $scope.model.geocode.geolocation.coordinates[0];
}
then you can simply use CoordinateX or whatever else you want to name it.
Related
I struggle to set feature IDs using mapbox GL.
I've read that you can auto-generate IDs using generateId:true in your source:
Whether to generate ids for the geojson features. When enabled, the
feature.id property will be auto assigned based on its index in the
features array, over-writing any previous values.
Except that I want to use my data at other places than just the mapbox map (a list of markers aside); so I would like to set them manually because I want to be able to target my feature on the map from my list aside. So, I don't want to use generateId:true here.
In the doc, their dataset example is like
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": "marker-iv1qi3x10",//an ID here
"title": "Burnham Park",
"description": "A lakefront park on Chicago's south side.",
"marker-size": "medium",
"marker-color": "#1087bf",
"marker-symbol": "marker-blue"
},
"geometry": {
"coordinates": [
-87.603735,
41.829985
],
"type": "Point"
},
"id": "0de616c939ce2f31676ff0294c78321b"//another ID here
}
]
}
So they have an ID in the feature object "id": "0de616c939ce2f31676ff0294c78321b", and another ID in the properties of that feature "id": "marker-iv1qi3x10".
I guess that the ID that mapbox uses internally for features (and auto-generated when generateId is set to true in your source) is the first one.
Let's say I set the IDs manually:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": "customPropId01"
},
"geometry": {
"coordinates": [
-87.603735,
41.829985
],
"type": "Point"
},
"id": "customID01"
}
]
}
When inspecting the data when the source has loaded, my custom IDs are still in place (using this code).
//when a specific source has been loaded
map.on('sourcedata', (e) => {
if (e.sourceId !== 'markers') return;
if (!e.isSourceLoaded) return;
console.log("SOURCE DATA LOADED",e.source);
});
But when I click on a marker on the map and that I log it, the ID property of my feature has been removed and is now undefined:
Rather than using my input source data to list my markers, I also had a look at querySourceFeatures, but this doesn't help since it returns only the features in the map bouding box - and I want my listing to display all the features, that is why I need to use the "raw" source data there.
This is driving me crazy.
Does anyone knows why the IDs are unset and how I could fix this ?
Thanks !
Your id is a string. But if you want preserve your id, this string should be cast in integer like the doc explain:
Features are identified by their id attribute, which must be an integer or a string that can be cast to an integer.
I found out that you can set promoteId to the feature property you want to use as IDs :
map.addSource('markers',{
type:"geojson",
data:"http://www.example.com/markers.geojson",
promoteId:'unique_id'
})
With promoteId:'unique_id', the property unique_id of my features will be used to set each feature's ID.
There are several question on the subject, but none of them seem to address this particular issue nor does the documentation on JSON Schema, so maybe it cannot be done.
The issue is that I have an array that can have any of 4 strings as values, easy enough to achieve with this schema:
...
"attributes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"controls",
"autoplay",
"muted",
"loop"
]
},
"additionalItems": false
}
...
So the values in the array can only be one of those four. Nevertheless, "controls" must always be part of the array, while the other three are optional. If it was an array of objects we could make this required, but I'm not sure how to check for an array having a specific value.
Thanks for any help!
You can use the contains keyword:
"attributes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"controls",
"autoplay",
"muted",
"loop"
]
},
"contains": {
"const": "controls"
},
"additionalItems": false
}
From the specification:
6.4.6. contains
The value of this keyword MUST be a valid JSON Schema.
An array instance is valid against "contains" if at least one of its
elements is valid against the given schema.
I'm using mongodb to store my data. My collection consists in a list of objects identified by a type a list of other objects for each of them.
An example of my collection is:
[
{
"type": "a",
"properties": [
{
"value": "value_a",
"date": "my_date_a"
},
{
"value": "value_b",
"date": "my_date_b"
},
...
]
},
...
]
Based on the above data structure, I want to retrieve all collections by a given type, taking for each of them only one element in the nested array (reducing the nested list to a list of only one element).
So, given a type "a", an example of the result may be:
[
{
"type": "a",
"properties": [
{
"value": "value_a",
"date": "my_date_a"
}
]
},
...
]
I'm started trying this query { "type": "a" } to filter the collections. But, how can I do to take only one "properties" element? I cannot use the "slice" operator.
Thanks a lot.
I'm assuming from your reference to slice, that you're not interested in matching a particular nested element, and rather just getting a value at a fixed index (eg, 0).
If you're willing to use the aggregation pipeline, you can use arrayElementAt within a projection:
db.collection.aggregate([
// matches documents with type 'a'
{ $match: { type: 'a' } },
// creates a new document for each
{ $project: {
// that contains the original value for type
type: 1,
// and the first element from the original properties for properties
properties: { $arrayElemAt: [ "$properties", 0 ] }
} }
])
Background
I am making a form using angular-schema-form
Setup
I am trying to make an array of items that a user can make using a form. So, the user can add as many items into the array as they want.
For now the items in the array contain a command type.
Command Type should be a dropdown containing SSH, REST, and whatever the user enters in as the personalized command type.
Code so far
SCHEMA
{
"type": "object",
"properties": {
"personalizedCommandType": {
"title": "Personalized Command Type",
"type": "string"
},
"commands": {
"type": "array",
"title": "Actions",
"items": {
"type": "object",
"properties": {
"commandType": {
"title": "Command Type",
"type": "string",
"enum": [
"REST",
"SSH"
]
}
}
}
}
}
}
FORM
[
{
"type": "help",
"helpvalue": "<h5>Command</h5>"
},
{
"key":"personalizedCommandType"
},
{
"title":"Command",
"key": "commands",
"items": [
"commands[].commandType"
]
}
]
One can test this code here: http://schemaform.io/examples/bootstrap-example.html . Just copy and paste in my code.
Question
As one can see, the code I have now has a field with Personalized Command Type and an array of dropdowns with the 2 options SSH and REST. But I want to drop to also contain the value of the Personalized Command Type once the user has entered it.
NOTE
copyValueTo does not seem to have the functionality that I want given that it can only change values in the model, but I want it to change the enum array in the schema.
Use the onChange option:
[
{
"type": "help",
"helpvalue": "<h5>Command</h5>"
},
{
"key":"personalizedCommandType"
onChange: "updateSchema(modelValue,form)"
},
{
"title":"Command",
"key": "commands",
"items": [
"commands[].commandType"
]
}
]
Update the Schema:
var defaultEnum = ["REST","SSH"];
$scope.updateSchema = function(modelValue,form) {
var currentEnum = $scope.schema.commands.items.properties.commandType.enum;
angular.copy(defaultEnum, currentEnum);
if (modelValue) {
currentEnum.push(modelValue);
};
$scope.$broadcast('schemaFormRedraw');
};
I'm trying to get into JSON schema definitions and wanted to find out, how to achieve a deeper object uniqueness in the schema definition. Please look at the following example definition, in this case a simple IO of a module.
{
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"required": ["modulIOs"],
"properties": {
"modulIOs": {
"type": "array",
"uniqueItems": true,
"items": {
"allOf": [
{
"type": "object",
"required": ["ioPosition","ioType","ioFunction"],
"additionalProperties": false,
"properties": {
"ioPosition": {
"type": "integer"
},
"ioType": {
"type":"string",
"enum": ["in","out"]
},
"ioFunction": {
"type":"string"
}
}
}
]
}
}
}
}
When I validate the following with i.E. draft-06 I get a positive validation.
{"modulIOs":
[
{
"ioPosition":1,
"ioType":"in",
"ioFunction":"240 V AC in"
},
{
"ioPosition":1,
"ioType":"in",
"ioFunction":"24 V DC in"
}
]
}
I'm aware that the validation is successfull because the validator does what he's intended to - it checks the structure of a JSON-object, but is there a possibility to validate object value data in deeper objects or do i need to perform the check elsewhere?
This is not currently possible with JSON Schema (at draft-7).
There is an issue raised on the official spec repo github for this: https://github.com/json-schema-org/json-schema-spec/issues/538
If you (or anyone reading this) really wants this, please thumbsup the first issue comment.
It's currently unlikely to make it into the next draft, and even if it did, time to impleemntations picking it up may be slow.
You'll need to do this validation after your JSON Schema validation process.
You can validate data value of your object fields by using JSON schema validation.
For example, if you need to check if ioPosition is between 0 and 100 you can use:
"ioPosition": {
"type": "integer",
"minimum": 0,
"maximum": 100
}
If you need to validate ioFunction field you can use regualr expression such as:
"ioFunction": {
"type": "string",
"pattern": "^[0-9]+ V [A,D]C"
}
Take a look at json-schema-validation.