Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Recently, I needed to make an extension that required multiple hypercubes with dimensions and measures that were able to be set by the user. The following is the solution I came up with. It could be a bit more generalized, and there's some other things to consider such as making selections, but it's a good starting point and an interesting topic, so I wanted to share with you.
The hypercubes need to be added to initialProperties. They can each be added within their own object in initialProperties, as below.
initialProperties: {
cube1: {
qHyperCubeDef: {
qDimensions: [],
qMeasures: [],
qInitialDataFetch: [{
qWidth: 2,
qHeight: 5000
}]
}
},
cube2: {
qHyperCubeDef: {
qDimensions: [],
qMeasures: [],
qInitialDataFetch: [{
qWidth: 2,
qHeight: 5000
}]
}
}
}
Now, you'll need to add the ability for users to define the dimensions and measures for each cube into the properties panel.
definition: {
type: "items",
component: "accordion",
items: {
cube1props: {
label: "Cube 1",
type: "items",
items: {
dimension: {
label: "Dimension",
type: "string",
expression: "always",
expressionType: "dimension",
ref: "cube1props.dimension"
},
measure: {
label: "Measure",
type: "string",
expression: "always",
expressionType: "measure",
ref: "cube1props.measure"
},
}
},
cube2props: {
label: "Cube 2",
type: "items",
items: {
dimension: {
label: "Dimension",
type: "string",
expression: "always",
expressionType: "dimension",
ref: "cube2props.dimension"
},
measure: {
label: "Measure",
type: "string",
expression: "always",
expressionType: "measure",
ref: "cube2props.measure"
}
}
}
}
}
This is where the interesting stuff happens. When the user updates one of the properties associated with a hypercube, we need to actually update the hypercube to reflect that. So in the extension's controller, we're going to watch for changes to the props for a cube, and then use the Backend API ApplyPatches method to update the cube.
//Set cube1
$scope.$watchCollection("layout.cube1props", function(props) {
$scope.backendApi.applyPatches([
{
"qPath": "/cube1/qHyperCubeDef/qDimensions",
"qOp": "replace",
"qValue": JSON.stringify([{qDef: {qFieldDefs: [props.dimension]}}])
},
{
"qPath": "/cube1/qHyperCubeDef/qMeasures",
"qOp": "replace",
"qValue": JSON.stringify([{qDef: {qDef: props.measure}}])
}
], false);
});
//Set cube2
$scope.$watchCollection("layout.cube2props", function(props) {
$scope.backendApi.applyPatches([
{
"qPath": "/cube2/qHyperCubeDef/qDimensions",
"qOp": "replace",
"qValue": JSON.stringify([{qDef: {qFieldDefs: [props.dimension]}}])
},
{
"qPath": "/cube2/qHyperCubeDef/qMeasures",
"qOp": "replace",
"qValue": JSON.stringify([{qDef: {qDef: props.measure}}])
}
], false);
});
That'll do it. Now the user can define a dimension and measure for each hypercube, and the hypercube will be patched accordingly. There's still some more to think about and some nice-to-have's with this approach, such as the ability to add variable numbers of dimensions and measures, allowing the user to set other properties of the hypercube, selections, and more. But, I think this pattern is a decent starting point.
Here's a link to a github repo I started around this idea, just in case you try this out and have anything cool to add.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.