cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
giammariam Frequent Visitor
Frequent Visitor

Create Custom visuals - Set measure color

Hello All,

 

I am developing custom visual for a clustered column chart and I am facing issue while implementing the color palette. 

 

I have added the color palette successfully but cannot use the color value for the series.

 

I can get it to work withCategory, but I need to set the color per the measure. I am having trouble implementing 

host.createSelectionIdBuilder().withMeasure() 

Once I select a color from palette it returns to the default.

 

Below is my code snipet for updating the view model and for rendering the Power BI properties.

 

        //set up viewmovdel
        //queries power bi to gather data that user is using for the visual
        //power bi makes VisualUpdateOptions available with every call to the update method
        private getViewModel(options: VisualUpdateOptions): ViewModel {

            //option.dataViews stores power bi's query data based on shape (e.g. tabular, matrix, tree, etc.)
            //configured in capabilities.json dataViewMappings.categorical
            //https://microsoft.github.io/PowerBI-visuals/docs/concepts/dataviewmappings/
            let dv = options.dataViews;

            //empty viewModel
            //The empty viewModel will be returned in the case where there is no data to show            
            let viewModel: ViewModel = {
                dataPoints: []
                , maxValue: 0
                , minValue: 0
                , highlights: false
            };

            //Check to make sure that all data that is needed is present before attempting to render the visual
            if (!dv
                || !dv[0]
                || !dv[0].categorical
                || !dv[0].categorical.categories
                || !dv[0].categorical.categories[0].source
                || !dv[0].categorical.values
                || !dv[0].metadata
            )
                return viewModel;

            //Only accepting one dataview
            //  The type that we are using is the categorical dataview
            let view = dv[0].categorical;

            //because we are accepting multiple measure types, iterate through each
            for (let i = 0, len = view.values.length; i < len; i++) {
                //We are only allowing for one series, so use index of 0 for categories
                let categories = view.categories[0];
                let values = view.values[i];
                let highlights = values.highlights;
                let objects = categories.objects;
                let metadata = dv[0].metadata;
                //metadata values will be used to populate the tooltip
                let categoryColumnName = metadata.columns.filter(c => c.roles["category"])[0].displayName;
                let measureColumnName = metadata.columns.filter(c => c.roles["measure"])[i].displayName;

                //iterate over all category-value pairs by index
                for (let j = 0, len = Math.max(categories.values.length, values.values.length); j < len; j++) {

                    //push datapoints into the view
                    viewModel.dataPoints.push({

                        category: <string>categories.values[j],
                        measure: <string>values.source.displayName,
                        value: <number>values.values[j],

                        //Since this property is data-bound, the property value is stored in the objects array
                        //if objects array exists and the color for 
                        color: objects && objects[j] && dataViewObjects.getFillColor(objects[i], {
                            objectName: "dataColors"
                            , propertyName: "fill"
                        }, null) || this.host.colorPalette.getColor(<string>categories.values[i]).value,

                        //a new SelectionIdBuilder is needed everytime a new selection id is needed
                        identity: this.host.createSelectionIdBuilder()
                            //slice over category column at position i
                            .withCategory(categories, j)
                            .createSelectionId(),
                        
                        measureIdentity: this.host.createSelectionIdBuilder()
                            .withMeasure(values.source.queryName)
                            .createSelectionId(),

                        //checks to see if the highlights array is defined
                        // then checks to see if any value exists in the same position of the corresponding
                        // values array, not the metadata array
                        highlighted: highlights ? highlights[j] ? true : false : false,

                        //set up the base tooltip for each datapoint
                        tooltips: [{
                            displayName: categoryColumnName,
                            value: <string>categories.values[j]
                        }, {
                            displayName: measureColumnName,
                            //if the value doesn't have a decimal, set value to 0 decimal places, otherwise set it 2 decimal places
                            value: ((<number>values.values[j]) == Math.floor(<number>values.values[j])) ? (<number>values.values[j]).toFixed(0) : (<number>values.values[j]).toFixed(2)
                        }]
                    });
                }
            }

            //populate the single-valued datapoints
            viewModel.maxValue = d3.max(viewModel.dataPoints, d => d.value);
            viewModel.minValue = d3.min(viewModel.dataPoints, d => d.value);
            //boolean to see whether or not there are any highlights
            viewModel.highlights = viewModel.dataPoints.filter(d => d.highlighted).length > 0;

            return viewModel;
        }

        //called by power bi everytime it needs to render the properties pane
        //for updating a property/property value in the properties pane
        //Driven by the object object in capabilities.json
        //called one time per property group in object object any time anything is updated in power bi
        //* Note - this takes place outside of the update loop
        public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {

            let propertyGroupName = options.objectName;
            let properties: VisualObjectInstance[] = [];

            switch (propertyGroupName) {
                case "xAxis":
                    properties.push({
                        objectName: propertyGroupName,
                        properties: {
                            show: this.settings.axis.x.show.value
                        },
                        selector: null
                    });
                    break;

                case "yAxis":
                    properties.push({
                        objectName: propertyGroupName,
                        properties: {
                            show: this.settings.axis.y.show.value
                            , invert: this.settings.axis.y.invert.value
                            , minimumDomain: this.settings.axis.y.minimumDomain.value
                            , integers: this.settings.axis.y.integers.value
                            , gridlines: this.settings.axis.y.gridlines.show.value
                        },
                        selector: null
                    });
                    break;

                case "dataColors":
                {
                    if (this.viewModel) {

                        //list out all data point properties that are needed
                        let allColorDatPoints = [];
                        this.viewModel.dataPoints.forEach(dp => {
                            allColorDatPoints.push({measureIdentity: dp.measureIdentity, measure: dp.measure, color: dp.color})
                        })

                        //get unique list of needed data point properties
                        let colorDatPoints = [];
                        for(let i=0; i<allColorDatPoints.length;i++){
                            let exists = false;
                            for(let j=0; j<colorDatPoints.length; j++){
                                if(//allColorDatPoints[i].measureIdentity == colorDatPoints[j].measureIdentity
                                //&& 
                                allColorDatPoints[i].measure == colorDatPoints[j].measure
                                && allColorDatPoints[i].color == colorDatPoints[j].color
                                ) {
                                    exists = true;
                                }
                            }
                            (!exists) ? colorDatPoints.push(allColorDatPoints[i]) : null
                        }
                        
                        for (let cdp of colorDatPoints) {

                            properties.push({
                                objectName: cdp.measure
                                , displayName: cdp.measure
                                , properties: {
                                    fill: cdp.color
                                },
                                selector: cdp.measureIdentity.getSelector()
                            });
                        }

                    }
                    break;
                }
            }
            return properties;
        }
    }
}

 

1 ACCEPTED SOLUTION

Accepted Solutions
Super User I
Super User I

Re: Create Custom visuals - Set measure color

With measures, I've only got it to work by using the queryName property from the measure DataViewMetadataColumn. If you use this rather than getSelector() against a SelectionId it should push it into the data view correctly.

If done right, you should see an objects key underneath your column in the metadata, e.g.:

image.png

You should be able to make out the queryName property from this screenshot too.

This should then get persisted into your object enumeration, e.g.:

image.png

Hopefully this is enough to get you moving; if not, you might need to share some code so we can have a look at specifics.

Good luck!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!




View solution in original post

2 REPLIES 2
Nishantjain Member
Member

Re: Create Custom visuals - Set measure color

Hi, 


Did you manage to resolve this issue? I am having the same problem and can't figure out how to read the measure colors

 

Thanks

Nishant

Super User I
Super User I

Re: Create Custom visuals - Set measure color

With measures, I've only got it to work by using the queryName property from the measure DataViewMetadataColumn. If you use this rather than getSelector() against a SelectionId it should push it into the data view correctly.

If done right, you should see an objects key underneath your column in the metadata, e.g.:

image.png

You should be able to make out the queryName property from this screenshot too.

This should then get persisted into your object enumeration, e.g.:

image.png

Hopefully this is enough to get you moving; if not, you might need to share some code so we can have a look at specifics.

Good luck!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!




View solution in original post

Helpful resources

Announcements
Exclusive LIVE Community Event #3 – Ask Arun Anything

Exclusive LIVE Community Event #3 – Ask Arun Anything

Join us in the third Triple A event!

Meet the 2020 Season 1 Power BI Super Users!

Meet the 2020 Season 1 Power BI Super Users!

It’s the start of a new Super User season! Learn all about the new Super Users and brand-new tiered recognition system.

Super User Challenge: Can You Solve These?

Super User Challenge: Can You Solve These?

We're celebrating the start of the New Super User season with our first ever Super User 'Can You Solve These?' challenge.

Power BI Desktop Update - February 2020

Power BI Desktop Update - February 2020

We are super excited for our update this month, as we are releasing two of our top community requests!

Power Platform Online Conference

Power Platform Online Conference

Join us for the first ever Power Platform Online Conference!

Top Kudoed Authors