One of the more powerful calls in the QIX Api is the ApplyPatches call. It allows you to dynamically add, change or remove basically any property of a generic object. With it, you can allow users to dynamically change visualizations: reorder data, change dimensions and measures, add limitation etc etc. But using it in your implementation can be tricky.
Parameters
The ApplyPatches call only has two parameters (plus the handle, identifying which object we are patching:
Name | Description | Mandatory | Type |
qPatches | Array of patches. | Yes | Array of NxPatch |
qSoftPatch | Patches are not saved | No | Boolean |
So it’s an arry and a boolean (true/false) flag. Let’s start with the flag. Setting the qSoftPatch flag to true does mean that the patched property is not saved, but it also has some other consequences:
- you can change objects that you otherwise cannot, like published objects, or objects in apps you cannot change
- the changes will only affect you, other users will not see them, they might very well apply a completely different patch to the same object
- the changes will only affect the current session. If you disconnect and connect again, they will be lost and you will start over with the original version of the object
So if your goal is to allow users to dynamically change visualizations you would want qSoftPatch to be true. While the default value false works OK in Qlik Sense Desktop, it’s generally not something you would want to use in a server environment.
The array of patches
The array is a bit more difficult. It’s an array so you can change several properties with one call. For example if you change dimension or measure you should consider changing the title too, and probably do that in the same call. Every entry(almost) in the array has three parameters:
Name | Description | Type |
qOp | Operation to perform. Add, remove or replace. | String |
qPath | Path to the property. | String |
qValue | The value of the property | String |
The first parameter, qOp, is an easy one. In most cases you want to change a property, use ‘replace’. Occasionaly you want to add a property, use ‘add’. Rarely you want to remove a property, in that case use ‘remove’.
The second parameter, qPath, is the path to the property, using / between the property names (not . as in javascript). Remember:
- you’re patching properties, not the layout, so it’s /qHyperCubeDef/… not qHyperCube
- for arrays you need to include the position in the array, and numbering starts with zero, so first dimension is /qHyperCubeDef/qDimensions/0/ etc
- property structures can be complicated, speciallly the hypercube..
- you can use my Chrome extension Add Sense to create the path argument. Show properties for the objects, switch to patch mode, copy the path
The second parameter, qPath, is the path to the property, using / between the property names (not . as in javascript). Remember:
- you’re patching properties, not the layout, so it’s /qHyperCubeDef/… not qHyperCube
- for arrays you need to include the position in the array, and numbering starts with zero, so first dimension is /qHyperCubeDef/qDimensions/0/ etc
- property structures can be complicated, speciallly the hypercube..
- you can use my Chrome extension Add Sense to create the path argument. Show properties for the objects, switch to patch mode
Some examples
A common case is when you want your users to be able to change the ordering of for example a table dynamically. Ordering of a hypercube is determined by the qInterColumnSortOrder property, an array with the column numbers in the order they should be used for sorting. If you want say the third column (which has number 2, since numbering starts with 0) you move the number 2 to the beginnging of the array and call applyPatches:
model.applyPatches( [{
qPath: '/qHyperCubeDef/qInterColumnSortOrder',
qOp: 'replace',
qValue: JSON.stringify(sortorder)
}], true );
You can find a more complete example in the mashup I showed at Qonnections back in 2015.
Another example is when you want to reverse the ordering of a hypercube. You do this by toggling the boolean value of qReverseSort in the dimension or measure where you want to change the order. For the first dimension this will be:
model.applyPatches( [{
qPath: '/qHyperCubeDef/qDimensions/0/qDef/qReverseSort',
qOp: 'replace',
qValue: JSON.stringify( !reversesort )
}], true );