Displaying Only Certain Columns/Properties with Keen DataViz - keen-io

I'm wondering how to display only certain columns on my table when I'm trying to do data visualization. Right now, every time that I do a table, it shows every single property or column. I tried to figure out how to only show certain columns properties by guessing based on the documentation for extraction within the keen.io docs (I've commented out my wrong guess)
var foo = new Keen.Query("extraction", {
eventCollection: "Purchases",
targetProperty: "zip",
// I've commented out line 7 because it doesn't work, it was just my guess on syntax...
// how do I only show certain columns of the table (columns are properties)
// vs. showing the entire table?
// propertyNames: ["zip","businessname"]
filters: [
{
"property_name" : "zip",
"operator" : "eq",
"property_value" : "80016"
},
{
"property_name" : "city",
"operator" : "eq",
"property_value" : "Aurora"
}]
});
client.draw(foo, document.getElementById("chart-09"), {
chartType: "table",
title: "Table"
});
https://gist.github.com/mrtannerjones/ba0cbd7340f2e016fcf2 - here is a link to the above code except on github in case something isn't formatted correctly.
Sorry if this question seems terribly basic or simple, I'm still really new at learning how to code.

Found the fix with a little help from David in the Keen.io Google group. I actually was just missing a comma after the 'property names', but what's more interesting to me is that the data visualization works with both camel case and with underscore separators. property_names and propertyNames both seem to work.

Related

How do I join and project a multi-map index?

I'm struggling to get my head around this one and I know the way to do this is through a custom index. Essentially, I have several collections that share some common properties, one of which is "system id" which describes a many-to-one relationship, e.g.
// Id() = "component:a"
{
"Name": "Component A"
"SystemId": "system:foo"
}
// Id() = "resource:a"
{
"Name": "Resource A",
"SystemId": "system:foo"
}
So these are two example objects which live in two different collections, Components and Resources, respectively.
I have another collection called "Notifications" and they have a RecipientID which refers to the Id of one of the entities described above. e.g.
// Id() = "Notifications/84-A"
{
"RecipientID": "component:a",
"Message": "hello component"
}
// Id() = "Notifications/85-A"
{
"RecipientID": "resource:a",
"Message": "hello resource"
}
The query that I want to be able to perform is pretty straight forward -- "Give me all notifications that are addressed to entities which have a system of ''" but I also want to make sure I have some other bits from the entities themselves such as their name, so a result object something like this:
{
"System": "system:foo",
"Notifications": [{
"Entity": "component:a",
"EntityName": "Component A",
"Notifications": [{
"Id": "Notifications/84-A",
"Message": "hello component"
}]
}, {
"Entity": "resource:a",
"EntityName": "Resource A",
"Notifications": [{
"Id": "Notifications/85-A",
"Message": "hello resource"
}]
}]
}
Where I am with it right now is that I'm creating a AbstractMultiMapIndexCreationTask which has maps for all of these different entities and then I'm trying to use the reduce function to mimic the relationship.
Where I'm struggling is with how these map reduces work. They require that the shape is identical between maps as well as the reduce output. I've tried some hacky things like including all of the notifications as part of the map and putting dummy values where the properties don't match, but besides it making it really hard to read/understand, I still couldn't figure out the reduce function to make it work properly.
How can I achieve this? I've been digging for examples, but all of the examples I've come across make some assumptions about how references are arranged. For example, I don't think I can use Include because of the different collections (I don't know how Raven would know what to query), and coming from the other direction, the entities don't have enough info to include or load notifications (I haven't found any 'load by query' function). The map portion of the index seems fine, I can say 'give me all the entities that share this system, but the next part of grabbing the notifications and creating that response above has eluded me. I can't really do this in multiple steps either, because I also need to be able to page. I've gone in circles a lot and I could use some help.
How about indexing the related docs ?
Something like this (a javascript index):
map("Notifications", (n) => {
let c = load(n.RecipientID, 'Components');
let r = load(n.RecipientID, 'Resources');
return {
Message: n.Message,
System: c.SystemId || r.SystemId,
Name: c.Name || r.Name,
RelatedDocId: id(c) || id(r)
};
})
Then you can query on this index, filter by the system value, and get all matching notifications docs.
i.e. sample query:
from index 'yourIndexName'
where System == "system:foo"
Info about related documents is here:
RavenDB Demo
https://demo.ravendb.net/demos/csharp/related-documents/index-related-documents
Documentation
https://ravendb.net/docs/article-page/5.4/csharp/indexes/indexing-related-documents

OpenUI5 sap.m.Input Currency Formatting

This looks to be answered many different times but I can't seem to get it working with my implementation. I am trying to format and limit the data in a sap.m.Input element. I currently have the following:
var ef_Amount = new sap.m.Input({
label: 'Amount',
textAlign: sap.ui.core.TextAlign.Right,
value: {
path: '/amount',
type: 'sap.ui.model.type.Currency'
}
});
The first problem is that it kind of breaks the data binding. When I inspect the raw data (with Fiddler) submitted to the server it is an array like this:
"amount": [1234.25,null]
The server is expecting a single number and as such has issues with the array.
When I use the following, the binding works as desired but no formatting is performed.
var ef_Amount = new sap.m.Input({
label: 'Amount',
textAlign: sap.ui.core.TextAlign.Right,
value: '{/amount}'
});
The second problem is that the data entered is not limited to numbers.
I have tried using sap.m.MaskedInput instead but I don't like the usage of the placeholders because I never know the size of the number to be entered.
And lastly, it would be nice if when focus is placed on the input field, that all formatting is removed and re-formatted again when focus lost.
Should I be looking into doing this with jQuery or even raw Javascript instead?
Thank you for looking.
the array output is a normal one according to documentation. So you need to teach your server to acccept this format or preprocess data before submission;
this type is not intended to limit your data input;
good feature, but ui5 does not support this, because the Type object has no idea about control and it's events like "focus" it only deals with data input-output. So you have to implement this functionality on your own via extending the control or something else.
I would suggest using amount and currency separately. It's likely that user should be allowed to enter only valid currency, so you can use a combobox with the suggestions of the available currencies.
So, after much work and assistance from #Andrii, I managed to get it working. The primary issue was that onfocusout broke the updating of the model and the change event from firing. Simply replacing onfocusout with onsapfocusleave took care of the issues.
The final code in the init method of my custom control:
var me = this;
var numberFormat = sap.ui.core.NumberFormat.getCurrencyInstance({maxFractionDigits: 2});
me.addEventDelegate({
onAfterRendering: function() {
// for formatting the figures initially when loaded from the model
me.bindValue({
path: me.getBindingPath('value'),
formatter: function(value) {
return numberFormat.format(value);
}
});
},
onfocusin: function() {
// to remove formatting when the user sets focus to the input field
me.bindValue(me.getBindingPath('value'));
},
onsapfocusleave: function() {
me.bindValue({
path: me.getBindingPath('value'),
formatter: function(value) {
return numberFormat.format(value);
}
});
}
});

How to make jqGrid dynamically populate options list based on row data

I am using jQrid version 3.8.1 with inline editing and each row in the grid has several dropdown lists to populate. When the user edits the row, I need to do an AJAX query to get the values for each of these lists. I've seen this post regarding how to do that. It appears that the dataUrl and buildSelect features are the standard answer here. There are a few issues I can't figure out though:
The row the user is editing has a value that must be passed into the dataUrl value. For example, say each row contains a field called "SpecialValue" and that for row 1, SpecialValue = 100. The dataUrl field for row 1 would be "http://my.services.com?SpecialValue=100". How do I do that?
Each row in the grid has about 10 select boxes that need to be populated. For efficiency reasons, I don't want to make 10 separate AJAX calls. It would be much better to make one call to get all the data, split it up, and fill each select box accordingly. Is that possible? I tried doing this inside onSelectRow but the grid ended up ignoring the values I put in there (I'm guessing do the ordering of the events that fire when you edit a row).
Edit:
After reading Oleg's answers and working on it more, it's clear to me that using dataUrl and buildSelect are not going to work well for me. The version of jqGrid I'm using doesn't support using dataUrl the way I would need. And even if it did I don't want to send multiple separate requests for each dropdown list.
I've decided to do one request when gridComplete fires to pull all the data needed for all dropdown lists into a single JSON structure. Then when the user selects a row to do inline editing, I will populate each list in the row from that JSON structure (the code below uses the getSelectValuesFromJSON() function for that--I don't give its definition but you can imaging it looks through the structure and gets an appropriate list of values to but in the list box).
I have a few candidate solutions but I'm not 100% happy with either one.
Solution 1:
Inside onSelectRow, I call editRow overriding the on oneditfunc to get the data out of the grid that I need. Assume that the value in Field1 is required to get the values to be put into the list in Field2.
onSelectRow: function (index, status, e) {
jQuery('#my_grid').jqGrid('editRow', index, true, function(rowId) {
var f1Val = $('#my_grid').jqGrid('getCell', index, 'Field1');
var selectVals = getSelectValuesFromJSON(f1Val); //gets data out of previously loaded JSON structure
var select = $('#my_grid').find('tr[id="' + index + '"] td[aria-describedby="my_grid_Field2"] select');
_.each(selectVals, function(selectVal) {
$(select).append($("<option></option>").attr("value", selectVal).text(selectVal));
});
});
}
This works but I'm hesitant about the line
var select = $('#my_grid').find('tr[id="' + index + '"] td[aria-describedby="my_grid_Field2"] select');
which relies on this aria-describedby attribute that I don't know much about. Seems hacky and brittle.
Solution 2:
Make use of beforeSelectRow to dynamically change the model of the Field2 column when the user selects a row.
beforeSelectRow: function(index, e) {
var f1Val = getGridCellValue('#my_grid', index, 'Field1');
var values = getSelectValuesFromJSON(f1Val); //gets data out of previously loaded JSON structure
var valStr = "";
_.each(values, function(value) {
valStr += value + ":" + value + ";"
});
jQuery('#grid_pipes').setColProp('Field2', { editoptions: { value: valStr } });
return true;
}
This also works but I'm not sure about whether or not this is really a good idea. Is it valid to dynamically change the model of a column like that? What if the user has several rows selected at the same time? Isn't there only one model for a column? What would that mean?
To answer some of Oleg's questions, the dataType has been set to a function that uses $.ajax to post data to the server. I think I read that's not the recommended approach anymore. I inherited this code so I'm not sure why it was done that way but it probably won't change unless there is a really compelling reason.
The loadonce boolean is not specified so I guess that means it defaults to false.
Here is an abbreviated version of the column model (nothing terribly out of the ordinary):
colModel: [
{ name: 'PK', index: 'PK', hidden: true, editable: true, sortable: true, search: true },
{ name: 'Field1', index: 'Field1', hidden: true, editable: true, sortable: true, search: true },
{ name: 'Field2', index: 'Field2', sortable: false, editable: true, search: false, edittype: "select", editoptions: {} },
{ name: 'Field3', index: 'Field3', sortable: false, editable: true, search: false, edittype: "select", editoptions: {} },
...
]
You don't wrote which version of jqGrid you use currently, but dataUrl can be defined as callback function with (rowid, value, name) parameters, which have to return the URL which you can build dynamically based on the information. The feature exist starting with v4.5.3 (see the line). You can use getCell, getRowData or getLocalRow inside of the callback to get the data from another columns of the row. Thus you can solve your first problem relatively easy.
You second question seems to me absolutely independent from the first one. It's better to separate such questions in different posts to allow the searching engine better to index the information and so to help other people to find it.
There are no simple way how to solve the second problem, but one can sure suggest a solution, but one have to know much more details what you do and how you do. How you start inline editing (do you use inlineNav, formatter: "actions" or you call editRow directly)? Which version of jqGrid (till version 4.7), free jqGrid or Guriddo jqGrid JS you use? How the columns with selects are defined in colModel? Which datatype you use and whether loadonce: true you use? I recommend you to post separate question with the information.
UPDATE: If you have to use old version of jqGrid then you can't generate dataUrl full dynamically, but because you need to add only SpecialValue=100" part to the URL you can follow the trick which I described in many my old answers (the first one was probably here, but the choice on property names which asked the user could be misunderstood). You can use ajaxSelectOptions.data which will define the data parameters of jQuery.ajax request. The problem only that you can define only one ajaxSelectOptions.data property. So you can add the following jqGrid option:
ajaxSelectOptions: {
data: {
SpecialValue: function () {
var rowid = $myGrid.jqGrid("getGridParam", "selrow");
return $myGrid.jqGrid("getCell", rowid, "SpecialValue");
}
}
}
($myGrid is something like $("#grid"))
UPDATED: You used unknown functions getSelectValuesFromJSON, getLookupValuesFromJSON in the updated part of your question. Both of there seems to use synchronous Ajax request which is not good. Moreover you set editoptions.value for only one Field2 instead of setting all selects.
onSelectRow: function (rowid) {
var $myGrid = $(this);
$.ajax({
url: "someUrl",
dataType: "json";
data: {
specialValue: $myGrid.jqGrid("getCell", rowid, "Field1")
},
success: function (data) {
// for example response data have format:
// { "Field2": ["v1", "v2", ...], "Field3": ["v3", "v4", ...] }
var filed, str;
for (filed in data) {
if (data.hasOwnProperty(filed)) {
str = $.map(data[filed], function (item) {
return item + ":" + item
}).join(";");
$myGrid.jqGrid("setColProp", filed, {
editoptions: {
value: str
}
});
}
}
$myGrid.jqGrid("editRow", rowid, true);
}
});
}
Nevertheless the "Solution 2" is more close to what I would recommend you. It's not really important whether to use onSelectRow or beforeSelectRow. You can make asynchronous Ajax request to the server which returns information for all select which you need. After you get the response from the server (inside of success callback) you can set editoptions.value for all selects and only then you can start editRow. In the way you will be sure that editing of the line will use row specific options in all select.
Some additional remarks. I recommend you to verify gridview: true option in the grid. Additionally I suspect that you fill the grid in not full correct way because you have hidden PK column and you use index instead of rowid as the first parameter of beforeSelectRow and onSelectRow. It's very important to understand that the current implementation of jqGrid always assign id attribute on every row (<tr> element) of the grid. So you have to provide id information in every item of input data. If you want to display the id information to the user (and so to have column in colModel with the primary key) then you should just include key: true property in the column definition. For example you can add key: true to the definition of PK column and so you will have rowid (or index in your case) with the same value like PK. It simplify many parts of code. For example jqGrid send id parameter in the editing request to the server. It's practical to have PK in the request. Moreover if you use repeatitems: false format of jsonReader the you can include id: "PK" in the jsonReader instead of having hidden PK column. It informs jqGrid to get rowid from PK. jqGrid will save PK in id attribute of <tr> and you will don't need to have additional <td style="display:none"> with the same information in the grid.
The last remark. I would strictly recommend you to update the retro version jqGrid 3.8.1 to some more recent version, for example to free jqGrid. Even if you would use no features (like Font Awesome for example) you will have performance advantages, and the look of modern web browsers will looks much better. You should understand the jqGrid 3.8.1 was tested with old (and slow jQuery 1.4.2). The version used with Internet Explorer 8 as the latest IE version (IE9 was published later in March 2011) and it's more oriented on IE6/IE7. The look in modern Chrome/Firefox/Safari can be bad. Is it what you want?

Ember-data multi-word model fields not serialized properly

I'm seeing some odd behavior with some custom serializer code that I wrote.
I have a field in an Asset model called 'marketName'. My Rails backend expects this field to be called 'market_name'. I've extended the ActiveModelSerializer and have overridden the 'extractSingle' and 'serialize' methods.
The odd thing is this - for all the other fields in my Asset model that are not made up of multiple words - the serialization code that I've written works great. No issues. However - for any field containing multiple words - the serialization doesn't work completely, in that while it saves the Asset when created - it doesn't correctly populate the Asset model's 'marketName' field (and any other field that is made up of multiple words).
For example if I examine the 'marketName' field in the data inspector it appears as '{}'. If I change the name of any multi word field in my Asset model to be singular (aka change 'marketName' to 'name') and update the serialization code accordingly - everthing works great.
Any idea what's going on ?
Thanks
Dave
In the test of extractSingle() that the core team (see line 126, also show below incase link goes bad for future readers) did, they pass in the variables as super_villains, then later the normalize() included in ActiveModelSerializer changes it for them to superVillains.
So I think in your extractSingle assume the values are not yet camelCase, but still are still in underscore_format (e.g., "market_name"), and you should be golden!
test("extractSingle", function() {
env.container.register('adapter:superVillain', DS.ActiveModelAdapter);
var json_hash = {
home_planet: {id: "1", name: "Umber", super_villain_ids: [1]},
super_villains: [{
id: "1",
first_name: "Tom",
last_name: "Dale",
home_planet_id: "1"
}]
};
var json = env.amsSerializer.extractSingle(env.store, HomePlanet, json_hash);
deepEqual(json, {
"id": "1",
"name": "Umber",
"superVillains": [1]
});
env.store.find("superVillain", 1).then(async(function(minion){
equal(minion.get('firstName'), "Tom");
}));
});

Getting the header name on extjs4 grid

Im trying to get the column header for the cell im clicking, but im not finding the correct way to do it
Right now, im using this code to identify the column:
if (position.column == 5 /*this is column name*/)
Obviously this is a bad choice, since any change on the grid will have consequences on the code.
Once again, thanks for the help
Assuming you are using a Ext.Grid.Panel. There is a columns array that can be indexed into to give you the column definition. the "text" property will contain the displayed column name.
alert(gridPanel.columns[0].text); //Alerts the 1st columns' header text.
If this doesn't answer your question a little more context would be helpful. In which event are you capturing your position?
If you are trying to determine a better way to get your column position setting the grid's initial config selType property to 'cellmodel' will give you a Ext.selection.CellModel selection model whose select event would give you the current cell position (col, row).
var grid = Ext.create('Ext.grid.Panel', {
store: store,
columns: [{
id: 'common',
header: 'Collumn 1'
}, {
header: 'Column 2'
}
],
selModel: {
selType: 'cellmodel'
}
});
grid.getSelectionModel().addListener('select', function(selModel, record, row, column, eOpts){
alert(grid.columns[column].text);
});
The best method might depend on where the code is, but here is some code from the CellEditing plugin which might be a good place to start:
editColumnHeader = grid.headerCt.getHeaderAtIndex(position.column);
From there, text looks like it would work, you might also be able to use itemId if you set that in the column.