get possible enum values for field from model to view - mysql

I have defined my model with this field
base: {
type: 'string',
in: ['A', 'B', 'C']
}
I was wondering if there is a way I could get the possible enum values to use in the view for a dropdown or if I need to have the it hardcoded somewhere?

You can always retrieve the attributes of a model with <model>.attributes. For example, given:
// api/models/Foo.js
module.exports = {
attributes: {
base: {
type: 'string',
in: ['A', 'B', 'C']
}
}
};
You can access Foo.attributes.base.in or sails.models.foo.base.in later to retrieve the in values.

Related

Typescript: Convert JSON object to a class/interface object

I m trying to convert an API response to typescript class/interface.
Here the API returns a list of objects with some properties, but I need only few of the properties of the response object.
API Response Example:
[{
'Id' : 1,
'Name': 'test',
'Description: 'Test',
'PropertyX': 'x',
'PropertyY' : 'y'
},
...]
Typescript Class
Class Response {
Id: string;
Name: string;
}
Can you please suggest me what will be the best approach for converting the JSON object to a typescript object.
I would suggest creating an interface that describes the properties you are using in your app and ignore the rest:
So assuming your response looks like:
const response = [{
'Id' : 1,
'Name': 'test',
'Description': 'Test',
'PropertyX': 'x',
'PropertyY' : 'y'
}, {
'Id' : 2,
'Name': 'test2',
'Description': 'Test2',
'PropertyX': 'x2',
'PropertyY' : 'y2'
}
];
and you are only interested in Id and Name, just create an interface like so:
interface IMyObject {
Id: String;
Name: String;
}
then in the rest of your app you can cast the response to IMyObject[]
For example if a function uses your response:
function myFunction(response: IMyObject[]) { ... }
or if you need to return that type, you can do a direct cast like so:
return response as MyObject[];
EDIT: As mentioned in the comment below, simply casting your object to IMyObject does not remove the extra properties you are not interested in.
To do so, use .map:
const formattedResponse: IMyObject = reponse.map(item => {
Id: item.Id,
Name: item.Name
});
You can use
forEach method and create a new object with the properties you require.
myarray=[];
ngOnInit() {
this.myvalues();
}
myMethod()
{
const response = [{
'Id' : 1,
'Name': 'test',
'Description': 'Test',
'PropertyX': 'x',
'PropertyY' : 'y'
}, {
'Id' : 2,
'Name': 'test2',
'Description': 'Test2',
'PropertyX': 'x2',
'PropertyY' : 'y2'
}
];
response.forEach(value=>{
this.myarray.push(
{
'ID':value.Id,
'Name':value.Name
}
)
});
console.log(this.myarray);
WORKING DEMO

Typescript convert an array to JSON

I have a complicated data structure that I need to convert to JSON. The problem is that my field names and values are in an array.
For instance, I have the following (simplified from my code base):
let SampleData = [
{ Field: 'Key', Value: '7'},
{ Field: 'City', Value: 'Some City'},
{ Field: 'Description', Value: 'Some Description'}
];
Basically my data is an array where the first element is the database column name, and the second element is the data in the column. I am trying to get a JSON object that is:
{ Key: 7, City: 'Some City', Description: 'Some Description' }
My real code has the fields and data is structures within the object, so I cannot simply use an Object.create() or Object.assign() as far as I can get working.
I have tried looping through to build a simple string and then use the JSON.parse to break it apart, but this seems like a lot of overhead for something I would have thought would be simpler.
As you asked, here's how to do it:
Mapping the array to an object
Converting the object to JSON
let array = [{
Field: 'Key',
Value: '7'
},
{
Field: 'City',
Value: 'Some City'
},
{
Field: 'Description',
Value: 'Some Description'
}
];
// #1 Mapping the array to an object...
let obj = {};
array.forEach(item => obj[item.Field] = item.Value);
// #2 Converting the object to JSON...
let json = JSON.stringify(obj);
console.log(json);
Bonus (ES6 + reduce):
const obj = array.reduce((acc, { Field, Value }) => ({ ...acc, [Field]: Value }), {});
you can try the below approach . I have used spread operator(ES6) and Object.assign to create the object ,then converted it into json string.
let SampleData = [
{ Field: 'Key', Value: '7'},
{ Field: 'City', Value: 'Some City'},
{ Field: 'Description', Value: 'Some Description'}
];
let obj = Object.assign(...SampleData.map( x => Object.values(x)).map(y => ({[y[0]]: y[1]})));
console.log(obj);
//{ Key: "7", City: "Some City", Description: "Some Description" }
console.log(JSON.stringify(obj));
I had a similar requirement and here is how I achieved it.
var ranges: segmentRange[] = new Array(2);
ranges[0] = { minimumPercentage: 50, maximumPercentage: 60 };
ranges[1] = { minimumPercentage: 30, maximumPercentage: 40 };
const segmentRanges = { segmentRanges: ranges };
return JSON.stringify(segmentRanges);
Output:
{"segmentRanges":[{"minimumPercentage":50,"maximumPercentage":60},{"minimumPercentage":30,"maximumPercentage":40}]}
HTH,

JSON-Schema Type and Value Dependencies

Is it possible to change a field's schema - according to another's value?
Note: I'm using Ajv
Example using Joi (A non JSON-Schema validator):
const schema = {
a: Joi.valid('x', 'y', 'z'),
b: Joi.string()
.when('a', { is: 'z', then: Joi.string(), otherwise: Joi.number() }),
};
The most direct way would be to have a $ref link depending on a $data pointer. Unfortunately, that isn't supported at the moment.
It's probably cleaner to do it using application logic, but if you're in a situation where you have to use a schema a more verbose way would be using oneOf. In that scenario your schema would be something like:
var ajv = new Ajv({
$data: true
});
let schema = {
oneOf: [
{
title: 'A is Z',
type: 'object',
properties: {
a: {
type: 'string',
enum: ['z']
},
b: {
type: 'string'
}
}
},
{
title: 'A is not Z',
type: 'object',
properties: {
a: {
type: 'string',
not: {
enum: ['z']
}
},
b: {
type: 'number'
}
}
}
]
};
let data = {
a: 'z',
b: '5'
};
ajv.validate(schema, data)
console.log('ERRORS: ', this.ajv.errors)
<script data-require="ajv#*" src="https://cdnjs.cloudflare.com/ajax/libs/ajv/5.3.0/ajv.bundle.js"></script>
EDIT: Since you're using AJV you can also take advantage of the AJV-Keywords module. It has a if / then / else operator that is currently a proposal for adding to the spec.

Correct normalizer syntax for normalizing JSON

I'm trying to use normalizer to normalize some JSON. My JSON looks like
total: 8029,
items: [
{
id: 1,
name: 'Jacket1',
sku: '123',
upc: '1',
price: '99.99',
images: ['url1', 'url2'],
category: 'clothing',
thumbnail:
'https://cdn.zeplin.io/5969021e44c5978909d5278b/assets/1CE5FF07-E70F-4413-85BF-49C08AA559DE.png',
}, ...
and from the examples, I thought this might work
const itemSchema = new schema.Entity('items')
const itemsSchema = new schema.Entity('result', {
items: [itemSchema],
})
const foo = normalize(fakeDatabase, itemsSchema)
But I end up with one result that is undefined, and that undefined value has some funky stuff in it.
What am I doing wrong?
I don't believe itemsSchema is necessary. Try either:
normalize(fakeDatabase, { items: new schema.Array(itemSchema) })
or
normalize(fakeDatabase, { items: [itemSchema] })

How to modify select objects in a JSON collection w/lodash

I'm looking for a performant way to update selected records in a collection based on the presence of the record's ID in a reference array. For example, given a reference array of [1,2,5] I want each record in the collection with those IDs to be given an attribute of $selected: true. Each record in the collection will be associated with a checkbox in the view and $selected items will be checked (fiddle)
I've started with the approach below (coffeescript) but I'm new to Lodash so I thought I'd ask for some feedback. Also, I'm not sure what the cleanest way is to set $selected: false to the alternate records?
# Whole Collection
collection = [
{id:1, name: "one"},
{id:2, name: "two"},
{id:3, name: "three"},
{id:4, name: "four"},
{id:5, name: "five"}
]
# Mark subset as selected
for id in [1,2,5]
_.where( collection, 'id':id ).forEach( (record) ->
record.$selected = true
)
Here's a fiddle...
http://jsfiddle.net/zd78e4bj/
EDIT
Added reference to two-way binding $selected elements to checkboxes in the view
I would do something like this (sorry it's not CoffeScript, but you get the idea):
var collection = [
{ id:1, name: 'one' },
{ id:2, name: 'two' },
{ id:3, name: 'three' },
{ id:4, name: 'four' },
{ id:5, name: 'five'}
];
var ids = [ 1, 2, 5 ];
_(collection)
.indexBy('id')
.at(ids)
.each(_.ary(_.partialRight(_.assign, { $selected: true }), 1))
.value();
console.log(collection);
// →
// [
// { id: 1, name: 'one', $selected: true },
// { id: 2, name: 'two', $selected: true },
// { id: 3, name: 'three' },
// { id: 4, name: 'four' },
// { id: 5, name: 'five', $selected: true }
// ]
First, we create an intermediary object using indexBy(). The keys are the id values in collection. Next, we pass at() the ids we're interested in. This builds a new collection containing only the ids we're after.
The last step is to use each() to add the $selected property. This is done by combining partialRight(), assign(), and ary(). The partially-applied argument is the new $selected property. We use ary() to make sure the callback passed to each() only has one argument.
You can use the map or forEach function to do all of this either in Lodash or native JavaScript. Map creates a new list and forEach will mutate the existing list.
The key to these is the transformation function. This function will set the $selected to true or false if it exists or not in the ids collection.
function mark(item) {
item['$selected'] = (ids.indexOf(item.id) > -1);
return item;
}
You could build a more generic transformer using:
function markItemByList(list, property, searchField) {
return function(item) {
item[property] = (list.indexOf(item[searchField]) > -1);
return item;
}
}
Coffeescript would be:
markItemByList = (list, property, searchField) ->
(item) ->
item[property] = (list.indexOf(item[searchField])) > -1)
item
If you want a mutable implementation:
function select(ids, collection) {
collection.forEach(markItemByList(ids, '$selected', 'id'));
}
Here's a lodash immutable implementation:
function select(ids, collection) {
return _.map(collection, markItemByList(ids, '$selected', 'id'));
}
Here's a pure JavaScript immutable implementation:
function select(ids, collection) {
return collection.map(markItemByList(ids, '$selected', 'id'));
}
Here's an angular implementation:
angular.forEach(collection, markItemsByList(ids, '$selected', 'id'));