I've this JSON:
{
"world": [{
"name": {
"en": "America"
},
"type": "continent",
"children": [{
"type": "state",
"name": {
"en": "Florida"
}
}, {
"type": "state",
"name": {
"en": "Hawaii"
}
}]
}, {
"name": {
"en": "Europe"
},
"type": "continent",
"children": [
]
}]
}
I need to do two select. The first contain the selection of type "continent", the other one based on the first must be showed if the first one children's are > 0 and contain the selection of the states.
You can do this,
<select name="client" ng-model="selectedRequest.continent" ng-options="c.name.en for c in clients.world" required></select>
<select id="department" ng-model="selectedRequest.state" ng-options="d.name.en for d in selectedRequest.continent.children"></select>
DEMO
EDIT
Updated fiddle disabling select if children is empty
Related
I'm trying to code an example that shows two dropdowns: one for countries, and one for related states/provinces. When you choose a country on the first dropdown, the values of the second dropdown should be updated to display only the provinces/states of the selected country. Usually this is accomplished using some sort of Ajax call, but in this case the requirement is to try it purely with react-jsonschema-form. Is this actually possible ? I have seen several examples using dependencies / references, but none solving this particular scenario.
So far I came up with this: https://codesandbox.io/s/fervent-cherry-lokjk?file=/src/App.js
{
"definitions": {
"Countries": {
"title": "Country",
"type": "object",
"properties": {
"country": {
"type": "string",
"enum": [
"CANADA",
"USA",
"MEXICO"
]
}
},
"dependencies": {
"country": {
"oneOf": [
{
"properties": {
"country": {
"enum": [
"CANADA"
]
},
"province": {
"type": "string",
"title": "Province",
"enum": [
"AB",
"BC",
"MB"
]
}
}
},
{
"properties": {
"country": {
"enum": [
"USA"
]
},
"province": {
"type": "string",
"title": "State",
"enum": [
"AL",
"AK",
"AR"
]
}
}
},
{
"properties": {
"country": {
"enum": [
"MEXICO"
]
},
"province": {
"type": "string",
"title": "State",
"enum": [
"AGS",
"BC",
"BCS"
]
}
}
}
]
}
}
}
},
"title": "Demo for countries",
"type": "object",
"properties": {
"currentCountry": {
"$ref": "#/definitions/Countries",
"title": "Select country / province / state"
}
}
}
which basically can render a Country dropdown and a State/Province dropdown. When selecting a country, the corresponding state/province dropdown is updated correctly with the new set of enum values.
However, with this approach, the form will submit a field named "currentCountry" with two properties inside, the country and the province
currentCountry: { country: "USA" , province: "AL" }
but of course the idea is to submit "country" and "province" as two different form fields, without the need to be wrapped.
So, does anyone know how to achieve this typical use case ? Is there any best approach to it using JSON schemas ?
Maybe having to code a custom widget ? (I would like to avoid that if possible)
Thanks in advance !
After playing a bit more, seems I found the solution. A correct schema that does exactly what is needed is this one:
{
title: "Demo for countries",
type: "object",
properties: {
country: {
type: "string",
title: "Country",
enum: ["CANADA", "USA", "MEXICO"]
}
},
dependencies: {
country: {
oneOf: [
{
properties: {
country: {
enum: ["CANADA"]
},
province: {
type: "string",
title: "Province",
enum: ["ALBERTA", "BRITISH COLUMBIA", "MANITOBA"]
}
}
},
{
properties: {
country: {
enum: ["USA"]
},
province: {
type: "string",
title: "State",
enum: ["ALABAMA", "OREGON", "ARKANSAS"]
}
}
},
{
properties: {
country: {
enum: ["MEXICO"]
},
province: {
type: "string",
title: "State",
enum: ["JALISCO", "BAJA CALIFORNIA", "CHIAPAS"]
}
}
}
]
}
}
}
and the above codesandbox example has been updated to reflect this change.
Happy to know this scenario can be achieved with JSON schemas !
I have a mongo collection called settings
{
"_id": "123",
"type": "subject",
"name": "Main",
"list": [{
"_id": "123",
"name": "Maths"
}, {
"_id": "123",
"name": " Physics"
}]
}
{
"_id": "123",
"type": "exam",
"name": "Activities",
"list": [{
"_id": "123",
"name": "Reading"
}, {
"_id": "123",
"name": "Fluency"
}]
}
Note: the values provided in my mongo is only for reference purpose.
Now I have generated an array with the records in settings collection
self.sample = function() {
self.settingsObj = {}
// console.log(self.settings)
_.each(self.settings, function(settings) {
//_.each(self.settings, function(settings) {
if (!self.settingsObj[settings.type]) {
self.settingsObj[settings.type] = []
}
self.settingsObj[settings.type] = settings.list
})
console.log(self.settingsObj)
}
When I console the settingsObj I get result like this in my console
Object {subject: Array[2], exam: Array[2]}
Now I want to loop this inside a scope variable
$scope.search = [{
"name": "",
"data": ""
}]
inside this name i want to get the object name in this situation subject,exam and inside loop i want to loop the arrays for subject and exam.
I tried another ._each, and I got the key and value but how can I loop them correctly.
Otherwise please help me in generating subject and exams as different array
I'm not very sure if I understand your question.
But if I see well you're using a Lodash.js library so I provide below script using a lodash:
I assume that you have settings variable like this:
var settings = [ {
"_id": "123",
"type": "subject",
"name": "Main",
"list": [{
"_id": "123",
"name": "Maths"
}, {
"_id": "123",
"name": " Physics"
}]
}
,
{
"_id": "123",
"type": "exam",
"name": "Activities",
"list": [{
"_id": "123",
"name": "Reading"
}, {
"_id": "123",
"name": "Fluency"
}]
}];
And I create functions for process those settings:
function createSearch(settings){
return _(settings).flatMap(toSearchArray).value();
}
function toSearchArray(setting){
return _(setting.list).map("name").map(toSearchObject).value()
function toSearchObject(data){
return {
name: setting.type,
data: data
}
}
}
And when you call createSearch(settings)
you will receive this result:
[
{
"name": "subject",
"data": "Maths"
},
{
"name": "subject",
"data": " Physics"
},
{
"name": "exam",
"data": "Reading"
},
{
"name": "exam",
"data": "Fluency"
}
]
Hopefully this is what you need.
After we have created a productType and have its type id, how can we set custom attributes during product create API calling. Until now what I've been doing is 1st, create the product, then update the custom attribute. But, I am unable to do so with the required attributes.
you can supply all the custom attributes in the product creation payload. Example - here I provide values for attributes brand on the master variant, for a previously created product type which specifies that there is an attribute called Brand:
{
"productType": {
"typeId": "product-type",
"id": "6c06998a-c576-4a8d-8ace-dc306d70e1d1"
},
"name": {
"en": "Some Product"
},
"slug": {
"en": "product_slug_sdfsdfsdfdsdfsdfdssdf"
},
"masterVariant": {
"prices": [{
"value": {
"centAmount": 2500,
"currencyCode": "EUR"
},
"country": "US"
}],
"attributes": [{
"name": "brand",
"value": "Hugo Boss"
}]
},
"variants": [{
"prices": [{
"value": {
"centAmount": 2600,
"currencyCode": "EUR"
},
"country": "US"
}],
"attributes": [{
"name": "brand",
"value": "Hugo Boss"
}]
}]
}
This is using angular-formly and i have created multiple-checkbox template as follows:
<script type="text/ng-template" id="multi-checkbox-template.html">
<div class="radio-group"
ng-class="{'has-error': options.formControl.$invalid}">
<label class="control-label">
{{options.label}}
{{options.required ? '*' : ''}}
</label>
<div class="radio"
ng-repeat="(key, option) in options.options">
<label>
<input type="checkbox"
formly-dynamic-name="id + '_'+ $index"
formly-custom-validation="options.validators"
id="{{id + '_'+ $index}}"
aria-describedby="{{id}}_description"
ng-value="option.value"
ng-required="options.required"
ng-model="$parent.model[$parent.options.key || $parent.index][option.name]">
{{option.name}}
</label>
<p id="{{id}}_description"
class="help-block"
ng-if="option.description">
{{option.description}}
</p>
</div>
</div>
</script>
This is config:
formlyConfigProvider.setType(
{
name: 'multi-checkbox',
templateUrl: 'multi-checkbox-template.html',
wrapper: ['bootstrapLabel', 'bootstrapHasError']
}
This is controller:
{
"key": "Q2",
"type":'multi-checkbox',
"templateOptions": {
"label": "What languages are you familiar with?",
"options": [
{ {
"name": "spanish",
"value": "spnsh"
},
{
"name": "french",
"value": "frnch"
},
{
"name": "more",
"value": "more"
}
]
}
}
];
Problem is that, doesn't show anything is the page even though error. I knew that path is correct regarding to the server response
`GET /multi-checkbox-template.html 200 1ms
This is warning i am getting,
angular-formly-bootstrap formly-field apiCheck failed! Required `label` not specified in `Argument 1/value/templateOptions`. Must be `String` https://github.com/formly-js/angular-formly/blob/6.10.0/other/ERRORS_AND_WARNINGS.md#formly-field-type-apicheck-failed
You passed:
{
"key": "Q2",
"type": "multi-checkbox",
"templateOptions": {
"to.label": "In what languages does your firm provide live chat support?",
"to.options": [
{
"name": "english",
"value": "eng"
},
{
"name": "spanish",
"value": "spnsh"
},
{
"name": "french",
"value": "frnch"
},
{
"name": "more",
"value": "more"
}
]
},
"$$hashKey": "object:592",
"data": {},
"validation": {
"messages": {}
},
"id": "formly_1_multi-checkbox_Q2_5"
}
With the types:
{
"key": "string",
"type": "string",
"templateOptions": {
"to.label": "string",
"to.options": {
"0": {
"name": "string",
"value": "string"
},
"1": {
"name": "string",
"value": "string"
},
"2": {
"name": "string",
"value": "string"
},
"3": {
"name": "string",
"value": "string"
}
}
},
"$$hashKey": "string",
"data": "Object",
"validation": {
"messages": "Object"
},
"value": "Function",
"runExpressions": "Function",
"resetModel": "Function",
"updateInitialValue": "Function",
"id": "string",
"initialValue": "undefined"
}
The API calls for:
{
"__apiCheckData": {
"strict": false,
"optional": false,
"type": "shape"
},
"shape": {
"templateOptions": {
"__apiCheckData": {
"strict": false,
"optional": false,
"type": "shape",
"error": "THIS IS THE PROBLEM: Required `label` not specified in `templateOptions`. Must be `String`"
},
"shape": {
"label": "String <-- YOU ARE MISSING THIS"
}
}
}
}
`
Please if there is any help i will be really thank you.
I think some of your references to options above should be referring to options.templateOptions instead (you can actually refer to this as to as a shortcut). For instance, options.label and options.options should be to.label and to.options. Not sure if this is the only issue though.
Also, the script tag business seems weird to me, but I always use:
template: require('path-to-my-template') and Webpack, so I can't be sure.
templateUrl in your formlyConfigProvider.setType() is not a directory link to your file.
the templateUrl is actually referring to the id attribute in your script tag
what you should do is:
formlyConfigProvider.setType(
{
name: 'multi-checkbox',
templateUrl: 'custom-template.html'
wrapper: ['bootstrapLabel', 'bootstrapHasError']
}
and in your template html file:
<script type="text/ng-template" id="custom-template.html">
<!-- your custom template should be here -->
</script>
My data looks like:
[
{
"_id": "531dbf8b9b9fc50000a8d611",
"active": true,
"client": {
"_id": "531dbf8b9b9fc50000a8d60e",
"name": "TR"
},
"company_id": "531dbf8b9b9fc50000a8d60c",
"createdOn": "2014-03-10T13:35:07.313Z",
"description": "Gentle Action Application Pads",
"dimensions": {
"weight": 22.4
},
"lot": [
],
"meta": {
"category": "Face",
"msrp": 7.75
},
"sku": "11002",
"unit_of_measure": "each",
"updatedOn": "2014-03-10T13:35:07.314Z"
},
{
"_id": "531dbf8b9b9fc50000a8d612",
"active": true,
"client": {
"_id": "531dbf8b9b9fc50000a8d60e",
"name": "TR"
},
"company_id": "531dbf8b9b9fc50000a8d60c",
"createdOn": "2014-03-10T13:35:07.317Z",
"description": "Skin Renewal System - Enriched (CA)",
"dimensions": {
"weight": 22.4
},
"lot": [
],
"meta": {
"category": "Face",
"msrp": 321.6
},
"sku": "11700CA",
"unit_of_measure": "each",
"updatedOn": "2014-03-10T13:35:07.318Z"
}
]
In my view, I have:
<input type="text" ng-model="receivingSku" placeholder="Locations loaded via $http" typeahead="sku for sku in getSku($viewValue) | filter:$viewValue" typeahead-on-select="selectedSku()" class="form-control">
I need the sku field for each item to be in the typeahead. How can I accomplish this?
Presently, I get an error:
Error: matches is undefined
You can loop over your original array and create an array of just SKU's:
var skus = origArray.map(function(e) {
return e.sku;
});
The new array can be used for typeahead.
PS - I'm not very familiar with typeahead. If typeahead is capable of peeking into objects, you don't need to do this.