Forum Discussion
Cannot successfully implement color picker on visual using table mapping
I am using the table type dataViewMapping.
I'm trying to store and retrieve colors, however colors don't save successfully.
I'm creating my selection Ids using the code from #77:
private static getSelectionIds(dataView: DataView, host: IVisualHost): powerbi.visuals.ISelectionId[] {
return dataView.table.identity.map((identity: DataViewScopeIdentity) => {
const categoryColumn: DataViewCategoryColumn = {
source: dataView.table.columns[0],
values: null,
identity: [identity]
};
return host.createSelectionIdBuilder()
.withCategory(categoryColumn, 0)
.createSelectionId();
});Then I populate the default colors:
this.GANTTEntries = options.dataViews[0].table.rows.map((v, i, a) =>
[
v[columnNames['stage']], //Stage name
a.map(i => i[columnNames['stage']]).indexOf(v[columnNames['stage']]), //Stage surrogate index
])
.filter((v, i) => v[1] === i) //Only keep stages groups (based on index)
.map((v, i) => {
let defaultColor: Fill = {
solid: {
color: this.host.colorPalette.getColor(options.dataViews[0].table.rows[i][2].toString()).value
}
}
return {
id: i,
content: v[0],
color: getCategoricalObjectValue<Fill>(options.dataViews[0].categorical.categories[0], i, 'colorSelector', 'fill', defaultColor).solid.color,
selectionId: selectionIds[i]
}
});Finally I implement my enumerate method:
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
let objectName = options.objectName;
let objectEnumeration: VisualObjectInstance[] = [];
switch (objectName) {
case 'colorSelector':
for (let GANTTElement of this.GANTTEntries) {
//debugger;
objectEnumeration.push({
objectName: objectName,
displayName: GANTTElement.content.toString(),
properties: {
fill: {
solid: {
color: GANTTElement.color
}
}
},
selector: GANTTElement.selectionId.getSelector()
});
}
break;
}
return(objectEnumeration);
}Color selections immediately revert to the default. The immediate reason is that there is no stored value (objects), but I am not sure how this all plumbs up and there are no examples that I can find other than the post for #77, which does not seem to work. I can't find the object in the dataview anywhere, and getCategoricalObjectValue returns the default value in all cases (as it can't either). This has taken longer than to implement the rest of the visual. Why is this so difficult?
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
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 :)
23 Replies
- aristogeitonFrequent Visitor
am using the table type dataViewMapping.
I'm trying to store and retrieve colors, however colors don't save successfully.
I'm creating my selection Ids using the code from #77:
private static getSelectionIds(dataView: DataView, host: IVisualHost): powerbi.visuals.ISelectionId[] { return dataView.table.identity.map((identity: DataViewScopeIdentity) => { const categoryColumn: DataViewCategoryColumn = { source: dataView.table.columns[0], values: null, identity: [identity] }; return host.createSelectionIdBuilder() .withCategory(categoryColumn, 0) .createSelectionId(); });Then I populate the default colors:
this.GANTTEntries = options.dataViews[0].table.rows.map((v, i, a) => [ v[columnNames['stage']], //Stage name a.map(i => i[columnNames['stage']]).indexOf(v[columnNames['stage']]), //Stage surrogate index ]) .filter((v, i) => v[1] === i) //Only keep stages groups (based on index) .map((v, i) => { let defaultColor: Fill = { solid: { color: this.host.colorPalette.getColor(options.dataViews[0].table.rows[i][2].toString()).value } } return { id: i, content: v[0], color: getCategoricalObjectValue<Fill>(options.dataViews[0].categorical.categories[0], i, 'colorSelector', 'fill', defaultColor).solid.color, selectionId: selectionIds[i] } });Finally I implement my enumerate method:
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject { let objectName = options.objectName; let objectEnumeration: VisualObjectInstance[] = []; switch (objectName) { case 'colorSelector': for (let GANTTElement of this.GANTTEntries) { //debugger; objectEnumeration.push({ objectName: objectName, displayName: GANTTElement.content.toString(), properties: { fill: { solid: { color: GANTTElement.color } } }, selector: GANTTElement.selectionId.getSelector() }); } break; } return(objectEnumeration); }Color selections immediately revert to the default. Why?
- v-viigCommunity Champion
Hello aristogeiton
The issue is in this code:
getCategoricalObjectValue<Fill>(options.dataViews[0].categorical.categories[0], i, 'colorSelector', 'fill', defaultColor).solid.color,
- The color for table mapping is kept in options.dataViews[0].table.rows[rowIndex].objects[0] instead of options.dataViews[0].categorical.categories[0].
- You should modify getCategoricalObjectValue function to handle options.dataViews[0].table.rows[rowIndex].objects[0] properly
Please let me know if you have any further questions.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- aristogeitonFrequent Visitor
Thanks for your response Igor. This still doesn't work. Is getSelectionIds() defined correctly? rows[index].objects is undefined in all cases.
- v-viigCommunity Champion
The getSelectionIds looks ok.
The rows[index].objects is undefiend if you haven't changed any settings of formatting panel.
Could you pleas share the whole source code as a zip?
Just want to debug it deeper.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals