Skip to content

Instantly share code, notes, and snippets.

@theredpea
Last active March 6, 2018 00:33
Show Gist options
  • Save theredpea/45a5fd5b9e784ae1455388ce06dd4c0c to your computer and use it in GitHub Desktop.
Save theredpea/45a5fd5b9e784ae1455388ce06dd4c0c to your computer and use it in GitHub Desktop.
LOAD * INLINE [
Val
0022
0023
0024
C001
C002
G001
SF01 ];
require('qlik').currApp().model.engineApp.getFieldDescription('Val')
{"method":"GetFieldDescription","handle":1,"params":["Val"],"delta":false,"jsonrpc":"2.0","id":25}
//Notice results no tags; qTags is empty; no qIsNumeric
{"jsonrpc":"2.0","id":25,"result":{"qReturn":{"qInternalNumber":6,"qName":"Val","qSrcTables":["INLFED"],"qCardinal":7,"qTotalCount":7,"qPossibleCount_OBSOLETE":-1,"qTags":[]}}}
//Therefore get the results, some can be qNum, some cannot:
require('qlik').currApp().field('Val').getData()
{"method":"GetLayout","handle":10,"params":[],"delta":true,"jsonrpc":"2.0","id":28}
{"jsonrpc":"2.0","id":28,"delta":true,"result":{"qLayout":[{"op":"add","path":"/","value":{"qInfo":{"qId":"MUcshDmDt","qType":"mashup"},"qSelectionInfo":{},"qListObject":{"qSize":{"qcx":1,"qcy":7},"qDimensionInfo":{"qFallbackTitle":"Val","qApprMaxGlyphCount":4,"qCardinal":7,"qSortIndicator":"N","qGroupFallbackTitles":["Val"],"qGroupPos":0,"qStateCounts":{"qLocked":0,"qSelected":0,"qOption":7,"qDeselected":0,"qAlternative":0,"qExcluded":0,"qSelectedExcluded":0,"qLockedExcluded":0},"qTags":[],"qDimensionType":"D","qGrouping":"N","qNumFormat":{"qType":"U","qnDec":0,"qUseThou":0},"qIsAutoFormat":true,"qGroupFieldDefs":["Val"],"qMin":0,"qMax":0,"qAttrExprInfo":[],"qAttrDimInfo":[]},"qExpressions":[],"qDataPages":[{"qMatrix":[[{"qText":"C001","qNum":"NaN","qElemNumber":3,"qState":"O","qFrequency":"1"}],[{"qText":"C002","qNum":"NaN","qElemNumber":4,"qState":"O","qFrequency":"1"}],[{"qText":"G001","qNum":"NaN","qElemNumber":5,"qState":"O","qFrequency":"1"}],[{"qText":"SF01","qNum":"NaN","qElemNumber":6,"qState":"O","qFrequency":"1"}],[{"qText":"0022","qNum":22,"qElemNumber":0,"qState":"O","qFrequency":"1"}],[{"qText":"0023","qNum":23,"qElemNumber":1,"qState":"O","qFrequency":"1"}],[{"qText":"0024","qNum":24,"qElemNumber":2,"qState":"O","qFrequency":"1"}]],"qTails":[],"qArea":{"qLeft":0,"qTop":0,"qWidth":1,"qHeight":7}}]}}}]}}
[
[
{
"qText": "C001",
"qNum": "NaN",
"qElemNumber": 3,
"qState": "O",
"qFrequency": "1"
}
],
[
{
"qText": "C002",
"qNum": "NaN",
"qElemNumber": 4,
"qState": "O",
"qFrequency": "1"
}
],
[
{
"qText": "G001",
"qNum": "NaN",
"qElemNumber": 5,
"qState": "O",
"qFrequency": "1"
}
],
[
{
"qText": "SF01",
"qNum": "NaN",
"qElemNumber": 6,
"qState": "O",
"qFrequency": "1"
}
],
[
{
"qText": "0022",
"qNum": 22,
"qElemNumber": 0,
"qState": "O",
"qFrequency": "1"
}
],
[
{
"qText": "0023",
"qNum": 23,
"qElemNumber": 1,
"qState": "O",
"qFrequency": "1"
}
],
[
{
"qText": "0024",
"qNum": 24,
"qElemNumber": 2,
"qState": "O",
"qFrequency": "1"
}
]
]
//Therefore making a selection of just text Values, will not do what you expect:
//Will not select Val=0024, will only Val=G001 , because I only use text:
require('qlik').currApp().field('Val').selectValues(['0024', 'G001'])
//I can fix 24, but then what do I pass for the text value?
require('qlik').currApp().field('Val').selectValues([24, ??])
//My only choice is to do a mixed selection, which Qlik handles fine:
require('qlik').currApp().field('Val').selectValues([24, 'G001'])
//Becomes:
{"method":"SelectValues","handle":9,"params":[[{"qIsNumeric":true,"qNumber":24},{"qText":"G001"}],false,false],"delta":false,"jsonrpc":"2.0","id":48}
//And the result is what I expect:
//Current Selections bar shows those 2 values are selected
//Val -> 2 of 7
// I confirmed against the specific business case where I was seeing an issue here
// that an *empty qTags array* is a symptom of a field that is inconsistent/ambiguous (i.e. in this case, has some field values with qText only, but some field values have qNum)
//And demonstrated that a workaround if you use selectMatch.
//Yep..., "you would not use selectValues if qIsNumeric is anything other than true"
//At first thought that the interface of the values passed into selectValues, was *same* as interface of returned data
//but not
//returned data looks like this:
//i.e. from GetListObjectData or the GetLayout on a CreateSessionObject List for a getField call
//On a filterpane (GetListObjectData)
//{"method":"GetListObjectData","handle":8,"params":["/qListObjectDef",[{"qTop":0,"qLeft":0,"qHeight":7,"qWidth":1}]],"delta":true,"jsonrpc":"2.0","id":27}
//{"jsonrpc":"2.0","id":27,"delta":true,"result":{"qDataPages":[{"op":"add","path":"/","value":[{"qMatrix":[[{"qText":"C001","qNum":"NaN","qElemNumber":3,"qState":"O"}],[{"qText":"C002","qNum":"NaN","qElemNumber":4,"qState":"O"}],[{"qText":"G001","qNum":"NaN","qElemNumber":5,"qState":"O"}],[{"qText":"SF01","qNum":"NaN","qElemNumber":6,"qState":"O"}],[{"qText":"0022","qNum":22,"qElemNumber":0,"qState":"O"}],[{"qText":"0023","qNum":23,"qElemNumber":1,"qState":"O"}],[{"qText":"0024","qNum":24,"qElemNumber":2,"qState":"O"}]],"qTails":[],"qArea":{"qLeft":0,"qTop":0,"qWidth":1,"qHeight":7}}]}]}}
//{"qText":"C001","qNum":"NaN","qElemNumber":3,"qState":"O"}
//On a field I called : require('qlik').currApp().field('Val').getData() (which it turns out CreateSessionObject and
//{"jsonrpc":"2.0","id":30,"delta":true,"result":{"qLayout":[{"op":"add","path":"/","value":{"qInfo":{"qId":"MUdYbzyW","qType":"mashup"},"qSelectionInfo":{},"qListObject":{"qSize":{"qcx":1,"qcy":7},"qDimensionInfo":{"qFallbackTitle":"Val","qApprMaxGlyphCount":4,"qCardinal":7,"qSortIndicator":"N","qGroupFallbackTitles":["Val"],"qGroupPos":0,"qStateCounts":{"qLocked":0,"qSelected":0,"qOption":7,"qDeselected":0,"qAlternative":0,"qExcluded":0,"qSelectedExcluded":0,"qLockedExcluded":0},"qTags":[],"qDimensionType":"D","qGrouping":"N","qNumFormat":{"qType":"U","qnDec":0,"qUseThou":0},"qIsAutoFormat":true,"qGroupFieldDefs":["Val"],"qMin":0,"qMax":0,"qAttrExprInfo":[],"qAttrDimInfo":[]},"qExpressions":[],"qDataPages":[{"qMatrix":[[{"qText":"C001","qNum":"NaN","qElemNumber":3,"qState":"O","qFrequency":"1"}],[{"qText":"C002","qNum":"NaN","qElemNumber":4,"qState":"O","qFrequency":"1"}],[{"qText":"G001","qNum":"NaN","qElemNumber":5,"qState":"O","qFrequency":"1"}],[{"qText":"SF01","qNum":"NaN","qElemNumber":6,"qState":"O","qFrequency":"1"}],[{"qText":"0022","qNum":22,"qElemNumber":0,"qState":"O","qFrequency":"1"}],[{"qText":"0023","qNum":23,"qElemNumber":1,"qState":"O","qFrequency":"1"}],[{"qText":"0024","qNum":24,"qElemNumber":2,"qState":"O","qFrequency":"1"}]],"qTails":[],"qArea":{"qLeft":0,"qTop":0,"qWidth":1,"qHeight":7}}]}}}]}}
//{"qText":"C001","qNum":"NaN","qElemNumber":3,"qState":"O","qFrequency":"1"}
//or a more relevant example:
//{"qText":"0024","qNum":24,"qElemNumber":2,"qState":"O","qFrequency":"1"}
//Notice how "qNum" is in there! Sometimes "NaN", sometimes an actual number like 24, but the property is "qNum"
//This is NOT the NxCell API? ...
//It is the QFieldValue API:
//https://help.qlik.com/en-US/sense-developer/September2017/Subsystems/APIs/Content/CapabilityAPIs/FieldAPI/QFieldValue.htm/
//Notice how qFrequency is optional ; the former returns it ; the latter doesnt;
///notice also qState is "O"; the NxCell API reminds that this stands for "Option":
//https://gist.github.com/theredpea/12d4c5a4d56c3acab7346a0847c1d6ae
//So this didnt work, thinking that I could pass *into* selectValues an object like {"qText":"0024","qNum":24,"qElemNumber":2,"qState":"O","qFrequency":"1"}
require('qlik').currApp().field('Val').selectValues([{qText:'0024', qNum: 24}, {qText:'G001'}])
//{"method":"SelectValues","handle":10,"params":[[{"qText":"0024","qNum":24},{"qText":"G001"}],false,false],"delta":false,"jsonrpc":"2.0","id":31}
//the result only selected 'G001'
//Even this didnt work: (omitting the qText in case that was the issue
require('qlik').currApp().field('Val').selectValues([{ qNum: 24}, {qText:'G001'}])
//{"method":"SelectValues","handle":9,"params":[[{"qNum":24},{"qText":"G001"}],false,false],"delta":false,"jsonrpc":"2.0","id":83}
//the result *still* only selected 'G001'
//But how did this work? Must be that Qlik transforms to a different engine call...
//require('qlik').currApp().field('Val').selectValues([24, 'G001'])
//Oh! Look at the call! "qNumber" is the property...
//{"method":"SelectValues","handle":10,"params":[[{"qIsNumeric":true,"qNumber":24},{"qText":"G001"}],false,false],"delta":false,"jsonrpc":"2.0","id":42}
//Specifically:
//{"qIsNumeric":true,"qNumber":24}
//What is *this* API? The QFieldValue API, above, described this API:
//https://help.qlik.com/en-US/sense-developer/September2017/Subsystems/APIs/Content/CapabilityAPIs/FieldAPI/QFieldValue.htm/
//But the selectValues function API... what is it? apparently it is called the "FieldValue"
//https://help.qlik.com/en-US/sense-developer/September2017/Subsystems/EngineAPI/Content/Classes/FieldClass/Field-class-SelectValues-method.htm#FieldValue
//And apparently just hte property name `qNumber` (vs `qNum` ) is not the *only* difference; i.e.necessary but not sufficient to make the SelectValues call work
//i.e. even this will fail:
//require('qlik').currApp().field('Val').selectValues([{qText:'0024', qNumber: 24}, {qText:'G001'}])
//notice the SelectValues call doesnt include qIsNumeric:
//{"method":"SelectValues","handle":10,"params":[[{"qText":"0024","qNumber":24},{"qText":"G001"}],false,false],"delta":false,"jsonrpc":"2.0","id":64}
//This however, is the most explicit Javascript; the resulting Engine call is almost exactly the same;
//that is, *both* specify qIsNumeric *and* qNumber, which is necessary and sufficient:
//require('qlik').currApp().field('Val').selectValues([{qText:'0024', qNumber: 24, qIsNumeric:true}, {qText:'G001'}])
//{"method":"SelectValues","handle":10,"params":[[{"qText":"0024","qNumber":24,"qIsNumeric":true},{"qText":"G001"}],false,false],"delta":false,"jsonrpc":"2.0","id":86}
//Which works!
//But remember the simpler/ simplest Javascript call works (because it produces identical Engine API call to the explicit call above)
//i.e. simplifyign the numeric value to just a Javascript int:
//require('qlik').currApp().field('Val').selectValues([24, {qText:'G001'}])
//And simplifying both:
//require('qlik').currApp().field('Val').selectValues([24, 'G001'])
//Of course a selectMatch will work too:
//require('qlik').currApp().field('Val').selectMatch('(0024|G001)')
//Not sure if selectMatch would be preferable for performance's sake
//With this test dataset; these two calls get responses exactly 2 miliseconds later than their requests:
//require('qlik').currApp().field('Val').selectMatch('(0023|C002)')
//{"method":"Select","handle":10,"params":["(0023|C002)",false],"delta":false,"jsonrpc":"2.0","id":219}
//require('qlik').currApp().field('Val').selectValues([23, 'C002'])
//{"method":"SelectValues","handle":10,"params":[[{"qIsNumeric":true,"qNumber":23},{"qText":"C002"}],false,false],"delta":false,"jsonrpc":"2.0","id":241}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment