Angular formly: calculate value of one field based on other fields input - angular-formly

json configuration:
{
"moduleconfigs": {
"create": [
{
"key": "Committed",
"type": "horizontalInput",
"templateOptions": {
"label": "Committed"
}
},
{
"key": "Uncommitted",
"type": "horizontalInput",
"templateOptions": {
"label": "Uncommitted"
}
},
{
"key": "Line",
"type": "horizontalInput",
"templateOptions": {
"label": "Line"
}
},{
"key": "Total",
"type": "horizontalInput",
"templateOptions": {
"label": "Total"
},
"expressionProperties":{
"value": function($viewValue, $modelValue, scope){
return scope.model.lineFill+scope.model.uncommitedBPD+scope.model.commitedBPD;
}
}
}
]
}
}
html:
<form>
<formly-for model="vm.myModel" fields="vm.myFields"></formly-form> </form>
I am new to angular formly. I am creating form using angular formly json. Total field should display sum of values provided in Committed+Uncommitted+Line fields. i am using expressionProperties but is not working.

I'm guessing you've moved on from this issue... however...
You are doing two things wrong.
First (1): They key value in the formly field configuration object is setting the value by that name on the model.
So your first field configuration object is:
{
"key": "Committed",
"type": "horizontalInput",
"templateOptions": {
"label": "Committed"
}
},
Then later you try to access that value using the key commitedBPDso you'll always get undefined.
Basically formly is setting the value input in that field on the model object with the key of Committed you need to change the key to match.
Second (2): I could be wrong but I don't think you can use an expression property to set the value like that. Formly will automatically respect value changes on the model so you're better off putting on onChange on the other formly field configuration objects that does the parsing and addition something like this:
{
"key": "Committed",
"type": "horizontalInput",
"templateOptions": {
"label": "Committed"
"onChange": addTotal
}
}...
function addTotal() {
//You have access to the model here because it's in your controller
// NOTE: the parseInput function you'll have to write yourself
vm.model.Total = parseInput(vm.model.Committed) + ...
}
All in all your biggest problem is trying to access the values from the model object with the wrong key

Yes, updating the model does not change form.input.value
The only way I've found is like this:
item.fieldGroup['Import'].formControl.setValue(333.33)

Related

How to insert data to bigquery table with custom fields with NodeJS?

I'm using npm BigQuery module for inserting data into bigquery. I have a custom field say params which is of type RECORD and accept any int,float or string value as a key value pair. How can I insert to such fields?
Looked into this, but could not find anything useful
[https://cloud.google.com/nodejs/docs/reference/bigquery/1.3.x/Table#insert]
If I understand correctly, you are asking for a map with ANY TYPE value, which is not support in BigQuery.
You may have a map with value type info with a record like below schema.
Your insert code needs to pick correct type_value to set.
{
"name": "map_field",
"type": "RECORD",
"mode": "REPEATED",
"fields": [
{
"name": "key",
"type": "STRING",
},
{
"name": "int_value",
"type": "INTEGER"
},
{
"name": "string_value",
"type": "STRING"
},
{
"name": "float_value",
"type": "FLOAT"
}
]
}

Logic App : Finding element in Json Object array (like XPath fr XML)

In my logic app, I have a JSON object (parsed from an API response) and it contains an object array.
How can I find a specific element based on attribute values... Example below where I want to find the (first) active one
{
"MyList" : [
{
"Descrip" : "This is the first item",
"IsActive" : "N"
},
{
"Descrip" : "This is the second item",
"IsActive" : "N"
},
{
"Descrip" : "This is the third item",
"IsActive" : "Y"
}
]
}
Well... The answer is in plain sight ... There's a FILTER ARRAY action, which works on a JSON Object (from PARSE JSON action).. couple this with an #first() expression will give the desired outcome.
You can use the Parse JSON Task to parse your JSON and a Condition to filter for the IsActive attribute:
Use the following Schema to parse the JSON:
{
"type": "object",
"properties": {
"MyList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Descrip": {
"type": "string"
},
"IsActive": {
"type": "string"
}
},
"required": [
"Descrip",
"IsActive"
]
}
}
}
}
Here how it looks like (I included the sample data you provided to test it):
Then you can add the Condition:
And perform whatever action you want within the If true section.

Loopback "Include" Filter Fails with hasManyThrough Relation

I have 3 models. 2 resource models, account(id, name) and widget(id, name), and 1 mapping model to map between the two widget_to_account(id, account_id, widget_id), to tell what widgets an account has access to, so to speak.
When stating the relationship between the models in their JSONs, using the guide in http://loopback.io/doc/en/lb3/HasManyThrough-relations.html, RESTful requests like "get widgets of account id=1" for example, works perfectly.
GET /accounts/1/widgets yields the widgets that account 1 has, yielding a widgets array:
[
{
"id": 1,
"name": "wg_user_mgr"
},
{
"id": 2,
"name": "wg_desc"
}
]
That's all good.
However, say I wanted to append this widgets array result along with the account object returned by a GET to the account model?. Loopback documentation suggests that this is done using the include keyword with the request, like so:
GET /accounts/1?filter[include]=widgets, returning hopefully an account model with it's allowed widgets:
{
"id": 1,
"name": "Account1Name",
"widgets": [
{
"id": 1,
"name": "wg_user_mgr",
"display_name": "User Manager"
},
{
"id": 2,
"name": "wg_desc",
"display_name": "Description"
}
]
}
However, what is actually returned by loopback with that request, is:
{
"id": 1,
"name": "Account1Name",
"widgets": []
}
Empty widgets array! When I look at the loopback SQL debugs, I see that it does go to the widget_to_account table and selects the entries of account_id=1, but interestingly it stop there and just returns an empty widgets array.
Any clues? The hasManyThrough loopback docs doesn't actually show any examples of using include like this to bridge two models that are connected via a mapping model.
My guess is they just forgot to code it in ¯\_(ツ)_/¯
UPDATE:
Doing some more digging around, I found the answer at https://groups.google.com/forum/#!topic/loopbackjs/sH7bKoqzU5c.
Where you define the relationships in the 2 resource models, you have to specifically define the "keyThrough" value.
NOT THIS:
"relations": {
"widgets": {
"type": "hasMany",
"model": "widget",
"foreignKey": "account_id",
"through": "widget_to_account"
}
}
BUT THIS:
"relations": {
"widgets": {
"type": "hasMany",
"model": "widget",
"foreignKey": "account_id",
"through": "widget_to_account",
"keyThrough": "account_id"
}
}
This is not made super clear, and is even stated incorrectly in the loopback api docs -.-
UPDATE:
Doing some more digging around, I found the answer at https://groups.google.com/forum/#!topic/loopbackjs/sH7bKoqzU5c.
Where you define the relationships in the 2 resource models, you have to specifically define the "keyThrough" value.
NOT THIS:
"relations": {
"widgets": {
"type": "hasMany",
"model": "widget",
"foreignKey": "account_id",
"through": "widget_to_account"
}
}
BUT THIS:
"relations": {
"widgets": {
"type": "hasMany",
"model": "widget",
"foreignKey": "account_id",
"through": "widget_to_account",
"keyThrough": "widget_id"
}
}
This is not made super clear, and is even stated incorrectly in the loopback api docs. I wish they'de stop this "auto-naming" paradigm they've been pushing around. Looking at loopback SO and the wider community, it's generally caused so much pain with models being named incorrectly, keys like this being set to totally arbitary names -.-

How to search through data with arbitrary amount of fields?

I have the web-form builder for science events. The event moderator creates registration form with arbitrary amount of boolean, integer, enum and text fields.
Created form is used for:
register a new member to event;
search through registered members.
What is the best search tool for second task (to search memebers of event)? Is ElasticSearch well for this task?
I wrote a post about how to index arbitrary data into Elasticsearch and then to search it by specific fields and values. All this, without blowing up your index mapping.
The post is here: http://smnh.me/indexing-and-searching-arbitrary-json-data-using-elasticsearch/
In short, you will need to do the following steps to get what you want:
Create a special index described in the post.
Flatten the data you want to index using the flattenData function:
https://gist.github.com/smnh/30f96028511e1440b7b02ea559858af4.
Create a document with the original and flattened data and index it into Elasticsearch:
{
"data": { ... },
"flatData": [ ... ]
}
Optional: use Elasticsearch aggregations to find which fields and types have been indexed.
Execute queries on the flatData object to find what you need.
Example
Basing on your original question, let's assume that the first event moderator created a form with following fields to register members for the science event:
name string
age long
sex long - 0 for male, 1 for female
In addition to this data, the related event probably has some sort of id, let's call it eventId. So the final document could look like this:
{
"eventId": "2T73ZT1R463DJNWE36IA8FEN",
"name": "Bob",
"age": 22,
"sex": 0
}
Now, before we index this document, we will flatten it using the flattenData function:
flattenData(document);
This will produce the following array:
[
{
"key": "eventId",
"type": "string",
"key_type": "eventId.string",
"value_string": "2T73ZT1R463DJNWE36IA8FEN"
},
{
"key": "name",
"type": "string",
"key_type": "name.string",
"value_string": "Bob"
},
{
"key": "age",
"type": "long",
"key_type": "age.long",
"value_long": 22
},
{
"key": "sex",
"type": "long",
"key_type": "sex.long",
"value_long": 0
}
]
Then we will wrap this data in a document as I've showed before and index it.
Then, the second event moderator, creates another form having a new field, field with same name and type, and also a field with same name but with different type:
name string
city string
sex string - "male" or "female"
This event moderator decided that instead of having 0 and 1 for male and female, his form will allow choosing between two strings - "male" and "female".
Let's try to flatten the data submitted by this form:
flattenData({
"eventId": "F1BU9GGK5IX3ZWOLGCE3I5ML",
"name": "Alice",
"city": "New York",
"sex": "female"
});
This will produce the following data:
[
{
"key": "eventId",
"type": "string",
"key_type": "eventId.string",
"value_string": "F1BU9GGK5IX3ZWOLGCE3I5ML"
},
{
"key": "name",
"type": "string",
"key_type": "name.string",
"value_string": "Alice"
},
{
"key": "city",
"type": "string",
"key_type": "city.string",
"value_string": "New York"
},
{
"key": "sex",
"type": "string",
"key_type": "sex.string",
"value_string": "female"
}
]
Then, after wrapping the flattened data in a document and indexing it into Elasticsearch we can execute complicated queries.
For example, to find members named "Bob" registered for the event with ID 2T73ZT1R463DJNWE36IA8FEN we can execute the following query:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "flatData",
"query": {
"bool": {
"must": [
{"term": {"flatData.key": "eventId"}},
{"match": {"flatData.value_string.keyword": "2T73ZT1R463DJNWE36IA8FEN"}}
]
}
}
}
},
{
"nested": {
"path": "flatData",
"query": {
"bool": {
"must": [
{"term": {"flatData.key": "name"}},
{"match": {"flatData.value_string": "bob"}}
]
}
}
}
}
]
}
}
}
ElasticSearch automatically detects the field content in order to index it correctly, even if the mapping hasn't been defined previously. So, yes : ElasticSearch suits well these cases.
However, you may want to fine tune this behavior, or maybe the default mapping applied by ElasticSearch doesn't correspond to what you need : in this case, take a look at the default mapping or, for even further control, the dynamic templates feature.
If you let your end users decide the keys you store things in, you'll have an ever-growing mapping and cluster state, which is problematic.
This case and a suggested solution is covered in this article on common problems with Elasticsearch.
Essentially, you want to have everything that can possibly be user-defined as a value. Using nested documents, you can have a key-field and differently mapped value fields to achieve pretty much the same.

Elasticsearch term filter on inner object field not matching

I have just organized my document structure to have a more OO design (e.g. moved top level properties like venueId and venueName into a venue object with id and name fields).
However I can now not get a simple term filter working for fields on the child venue inner object.
Here is my mapping:
{
"deal": {
"properties": {
"textId": {"type":"string","name":"textId","index":"no"},
"displayId": {"type":"string","name":"displayId","index":"no"},
"active": {"name":"active","type":"boolean","index":"not_analyzed"},
"venue": {
"type":"object",
"path":"full",
"properties": {
"textId": {"type":"string","name":"textId","index":"not_analyzed"},
"regionId": {"type":"string","name":"regionId","index":"not_analyzed"},
"displayId": {"type":"string","name":"displayId","index":"not_analyzed"},
"name": {"type":"string","name":"name"},
"address": {"type":"string","name":"address"},
"area": {
"type":"multi_field",
"fields": {
"area": {"type":"string","index":"not_analyzed"},
"area_search": {"type":"string","index":"analyzed"}}},
"location": {"type":"geo_point","lat_lon":true}}},
"tags": {
"type":"multi_field",
"fields": {
"tags":{"type":"string","index":"not_analyzed"},
"tags_search":{"type":"string","index":"analyzed"}}},
"days": {
"type":"multi_field",
"fields": {
"days":{"type":"string","index":"not_analyzed"},
"days_search":{"type":"string","index":"analyzed"}}},
"value": {"type":"string","name":"value"},
"title": {"type":"string","name":"title"},
"subtitle": {"type":"string","name":"subtitle"},
"description": {"type":"string","name":"description"},
"time": {"type":"string","name":"time"},
"link": {"type":"string","name":"link","index":"no"},
"previewImage": {"type":"string","name":"previewImage","index":"no"},
"detailImage": {"type":"string","name":"detailImage","index":"no"}}}
}
Here is an example document:
GET /production/deals/wa-au-some-venue-weekends-some-deal
{
"_index":"some-index-v1",
"_type":"deals",
"_id":"wa-au-some-venue-weekends-some-deal",
"_version":1,
"exists":true,
"_source" : {
"id":"921d5fe0-8867-4d5c-81b4-7c1caf11325f",
"textId":"wa-au-some-venue-weekends-some-deal",
"displayId":"some-venue-weekends-some-deal",
"active":true,
"venue":{
"id":"46a7cb64-395c-4bc4-814a-a7735591f9de",
"textId":"wa-au-some-venue",
"regionId":"wa-au",
"displayId":"some-venue",
"name":"Some Venue",
"address":"sdgfdg",
"area":"Swan Valley & Surrounds"},
"tags":["Lunch"],
"days":["Saturday","Sunday"],
"value":"$1",
"title":"Some Deal",
"subtitle":"",
"description":"",
"time":"5pm - Late"
}
}
And here is an 'explain' test on that same document:
POST /production/deals/wa-au-some-venue-weekends-some-deal/_explain
{
"query": {
"filtered": {
"filter": {
"term": {
"venue.regionId": "wa-au"
}
}
}
}
}
{
"ok":true,
"_index":"some-index-v1",
"_type":"deals",
"_id":"wa-au-some-venue-weekends-some-deal",
"matched":false,
"explanation":{
"value":0.0,
"description":"ConstantScore(cache(venue.regionId:wa-au)) doesn't match id 0"
}
}
Is there any way to get more useful debugging info?
Is there something wrong with the explain result description? Simply saying "doesn't match id 0" does not really make sense to me... the field is called 'regionId' (not 'id') and the value is definitely not 0...???
That happens because the type you submitted the mapping for is called deal, while the type you indexed the document in is called deals.
If you look at the mapping for your type deals, you'll see that was automatically generated and the field venue.regionId is analyzed, thus you most likely have two tokens in your index: wa and au. Only searching for those tokens on that type you would get back that document.
Anything else looks just great! Only a small character is wrong ;)

Resources