Forum Discussion

aristogeiton's avatar
aristogeiton
Frequent Visitor
8 years ago
Solved

Cannot successfully implement color picker on visual using table mapping

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

    [email protected]

  • 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

  • aristogeiton's avatar
    aristogeiton
    Frequent 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-viig's avatar
    v-viig
    Community Champion

    Hello aristogeiton

     

    The issue is in this code:

    getCategoricalObjectValue<Fill>(options.dataViews[0].categorical.categories[0], i, 'colorSelector', 'fill', defaultColor).solid.color,

     

    1. The color for table mapping is kept in options.dataViews[0].table.rows[rowIndex].objects[0] instead of options.dataViews[0].categorical.categories[0].
    2. You should modify getCategoricalObjectValue function to handle options.dataViews[0].table.rows[rowIndex].objects[0properly

     

    Please let me know if you have any further questions.

     

    Ignat Vilesov,

    Software Engineer

     

    Microsoft Power BI Custom Visuals

    [email protected]

      

     

    • aristogeiton's avatar
      aristogeiton
      Frequent Visitor

      Thanks for your response Igor. This still doesn't work. Is getSelectionIds() defined correctly? rows[index].objects is undefined in all cases.

      • v-viig's avatar
        v-viig
        Community 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

        [email protected]