Forum Discussion
Cannot successfully implement color picker on visual using table mapping
- 8 years ago
Please this code snippet below to fix the issues with color picker:
private static getSelectionIds( dataView: DataView, host: IVisualHost ): powerbi.visuals.ISelectionId[] { const queryName: string = dataView.table.columns[0].queryName; return dataView.table.identity.map((identity: DataViewScopeIdentity) => { const categoryColumn: DataViewCategoryColumn = { source: { queryName, displayName: null }, values: null, identity: [identity] }; return host.createSelectionIdBuilder() .withCategory(categoryColumn, 0) .withMeasure(queryName) .createSelectionId(); }); }Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- 8 years ago
Alright thank you !
For those with the same situation, I find a workaround.
You should use
d3.scale.ordinal().domain(data.map(d => d.dimension).range(color_library)
With color_library an array of color your users can pick ( I take 10 for my chart but you can use 3 or 20...).
Not the best solution, I have to admit but it works for now until I find something else :)
anandsoftweb Please take a look at this topic.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
Hi v-viig
I'm quite in the same situation as aristogeiton, I'm using a Table DataViewMapping and I don't know how to retrieve the object when I modify the color in Power BI.
I have already implemented this option in an other custom char with a Categorical DataViewMapping but with the table, it seems different.
I'll try to explain my issue.
I have a Table DataViewMapping
"dataViewMappings": [
{
"table": {
"rows": {
"select": [
{"for": {
"in": "Details"
}},
{"for": {
"in": "Yaxis"
}},
{"for": {
"in": "Xaxis"
}},
{"for": {
"in": "Dim2"
}},
{"for": {
"in": "Dim1"
}}
]}}
}]To get my data from the dataview, i use this code :
dataView.table.rows.forEach((row: DataViewTableRow) => {
const columns = this.getColumnGroupByRole(dataView.metadata.columns, row);
viewModel.DataPoints.push({
Details: <string>columns["Details"] ? <string>columns["Details"] : "Null",
Yaxis: <string>columns["Yaxis"] ? <string>columns["Yaxis"] : "Null",
Xaxis: <string>columns["Xaxis"] ? <string>columns["Xaxis"] : "Null",
Dim1: <string>columns["Dim1"] ? <string>columns["Dim1"] : "Null",
Dim2: <string>columns["Dim2"] ? <string>columns["Dim2"] : "Null",
color: this.host.colorPalette.getColor(<string>columns["Dim1"]).value,
identity: this.getSelectionIds(dataView, this.host)
});
});As you can see, my color is define by the value of my "Dim1" column. So, in my enumerateObjectInstances I wrote this :
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
let objectName = options.objectName;
let objectEnumeration: VisualObjectInstance[] = [];
switch (objectName) {
case "dataColors":
this.uniqueColorRetrieve(this.finaldata).forEach(d => {
objectEnumeration.push({
objectName: objectName,
displayName: d.name,
properties : {
fill: d.color
},
selector: null
});
});
break;
}
return objectEnumeration;
}With "FinalData", the data I use for my SVGs and "uniqueColorRetrieve", a function returning a list of {name,color} pair without duplicates.
I have the right number of color in my parameters in PBI, but when I pick an other color, it goes back to the default color.
I know that my problem is somewhere between my color definition and my color object but I can't find where....
I saw the situation of aristogeiton, but without the full code, I don't fully understand what it does.
Do you perhaps know what I do wrong ?
Thanks in advance !
- v-viig8 years agoCommunity Champion
FR5702 To parse color properly you should specify a selector for each item of finalData.
this.uniqueColorRetrieve(this.finaldata).forEach(d => { objectEnumeration.push({ objectName: objectName, displayName: d.name, properties : { fill: d.color }, selector: d.identity.getSelector(), }); });You should also parse color for row by using something like this:
row.objects[0] // It will contain properties. Please use console.log to figure out its structure.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- v-viig8 years agoCommunity Champion
To support such grouping you should start using categorical data mapping instead of table mapping.
Categorical mapping supports "group by" option.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- v-viig8 years agoCommunity Champion
Correct. You should have numeric data column in a data set. Such column will allow grouping that required to implement desired behavior.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- FR57028 years agoHelper I
Hi v-viig,
Thanks for your tips, I have a better understanding of how it works.
But I still have a problem...
To recap, if it's confusing for you, here what I'm doing:
1) I take all my datapoints (with their color define by
color: this.host.colorPalette.getColor(<string>columns["Dim1"]).value,
and identity define by
this.getSelectionIds(dataView, this.host)
with
private getSelectionIds( dataView: DataView, host: IVisualHost): powerbi.visuals.ISelectionId[] { const queryName: string = dataView.table.columns[0].queryName; return dataView.table.identity.map((identity: DataViewScopeIdentity) => { const categoryColumn: DataViewCategoryColumn = { source: { queryName, displayName: null }, values: null, identity: [identity] }; return host.createSelectionIdBuilder() .withCategory(categoryColumn, 0) .withMeasure(queryName) .createSelectionId(); }); })
2) I group them by my four dimensions = I create X groups
3) I represent them on my chart = 1 point per group
The result is this one :
And I want to be able to change the color of my groups depending on 1 Dimension ( Dim1).
As it needs the identity to bound my object with my data, I use the identity from my datapoints.
But how can I use all the identities of the datapoints having the same Dim1 value ? Because if I use an identity from my dataPoints, it'll not have any effect as the other dataPoints of his group won't be bound to my object and therefore won't change.
I tried to define an identity for each of my groups with :
this.host.createSelectionIdBuilder().withMeasure(list[i].Dim1).createSelectionId()
but it didn't change anything.
And when I change my Datapoints' identites by these group identities, my chart broke while my data are fine (I checked in my console).
My question is : How can I change my DataPoints' identities to group identities without breaking my chart ? Or is there an other solution ?
Thank you for your help, I really need it :)
- FR57028 years agoHelper I
Thanks v-viig I get the logic but I don't know how it can be apply to my case as I don't have any value data (all my data are text format).
How can I go from
"table": { "rows": { "select": [ {"for": { "in": "Details" }}, {"for": { "in": "Yaxis" }}, {"for": { "in": "Xaxis" }}, {"for": { "in": "Dim2" }}, {"for": { "in": "Dim1" }} ] }, "conditions": [{ "Details":{ "max": 1 }, "Yaxis":{ "max": 1 }, "Xaxis":{ "max": 1 }, "Dim1":{ "max": 1 }, "Dim2":{ "max": 1 } }] }to something similar to the examples 2 or 3
- v-viig8 years agoCommunity Champion
Don't have numbers? If so, there's no way to impelement desired behavior w/o using numbers.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- FR57028 years agoHelper I
Yes, I transform my data from text to numeric in my code, but what I get from my DataSource are all text data.
There no way to have this behaviour without numbers directly in my DataSource ? Or do I have to make all the transformation when I create my ViewModel/DataPoints in order to enable my color picker ?
- FR57028 years agoHelper I
Alright thank you !
For those with the same situation, I find a workaround.
You should use
d3.scale.ordinal().domain(data.map(d => d.dimension).range(color_library)
With color_library an array of color your users can pick ( I take 10 for my chart but you can use 3 or 20...).
Not the best solution, I have to admit but it works for now until I find something else :)