cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
paul-maessen
Resolver I
Resolver I

Trying to implement highlighting in Matrix Dataview

Hi,

 

I am trying to implement highlighting in a custom visual I am developing. This visual is using the Matrix dataViewMapping.

I am able to use selections in my Visual and  when enabling visual interactions I can select the highlight options in my visual (see image)

Screenshot 2020-07-24 at 15.41.46.png

 

 

 

 

 

 

But when I now select a value in another visual the selected point is not highlighted in my visual, which it should so if highlighting would work.

Because I am not sure what I am missing, I will add as much as information to this post. So it might get a bit long 🙂

 

I hope someone can help me to get this to work.

 

Thanks in advance!

 

Paul.

 

Below you will find the information:

 

The dataViewMappings-part of my capabilities.json:

 

"dataRoles": [
        {
            "name": "category",
            "kind": "Grouping",
            "displayName": "Category"
        },
        {
            "name": "value",
            "kind": "GroupingOrMeasure",
            "displayName": "Value"
        }
    ],
    "dataViewMappings": [
        {
            "conditions": [
                {
                    "value": {
                        "max": 1
                    },
                    "category": {
                        "max": 1
                    }
                }
            ],
            "matrix": {
                "rows": {
                    "for": {
                        "in": "category"
                    }
                },
                "values": {
                    "select": [
                        {
                            "for": {
                                "in": "value"
                            }
                        }
                    ]
                }
            }
        }
    ],
    "supportsHighlight": true,

 

 

I am using the GroupingOrMeasure-kind for 'value' so I can select Don't summarize for the measures that are selected for this value.

 

My dataViewModel looks like this:

 

export interface StripPlotViewModel {
    dataView: DataView;
    settings: StripPlotSettings;
    dataPoints: StripPlotPoint[];
    hasHighlights: boolean;
    isCategoryFilled: boolean;
    isValueFilled: boolean;
}

 

 

The StripPlotPoint-interface :

 

export interface StripPlotPoint extends SelectableDataPoint {
    category: PrimitiveValue;
    value: PrimitiveValue;
    opacity: number;
    highlight?: boolean;
    hasHighlights: boolean;
}

 

 

I am using a seperate file to define my behavior:

 

import * as d3 from "d3";

type Selection<T1, T2 = T1> = d3.Selection<any, T1, any, T2>;

import { interactivityBaseService as interactivityService } from "powerbi-visuals-utils-interactivityutils";
import IInteractiveBehavior = interactivityService.IInteractiveBehavior;
import IInteractivityService = interactivityService.IInteractivityService;
import ISelectionHandler = interactivityService.ISelectionHandler;

import { StripPlotPoint } from "./dataInterfaces";
import { IBehaviorOptions } from "powerbi-visuals-utils-interactivityutils/lib/interactivityBaseService";
import { StripPlotSettings } from "./settings";

export const DimmedOpacity: number = 0.2;
export const DefaultOpacity: number = 1.0;

const getEvent = () => d3.event;

export function getFillOpacity(
    selected: boolean,
    highlight: boolean,
    hasSelection: boolean,
    hasPartialHighlights: boolean
): number {
    if ((hasPartialHighlights && !highlight) || (hasSelection && !selected)) {
        return DimmedOpacity;
    }
    return DefaultOpacity;
}

export interface BehaviorOptions extends IBehaviorOptions<StripPlotPoint> {
    clearCatcher: Selection<any>;
    pointSelection: Selection<StripPlotPoint>;
    interactivityService: IInteractivityService<StripPlotPoint>;
    settings: StripPlotSettings;
}

export class Behavior implements IInteractiveBehavior {
    private options: BehaviorOptions;

    public bindEvents(options: BehaviorOptions, selectionHandler: ISelectionHandler) {
        this.options = options;
        let clearCatcher = options.clearCatcher;


        options.pointSelection.on("click", (dataPoint: StripPlotPoint) => {
            const event: MouseEvent = d3.event;
            console.log("clicked: ");
            console.log(event);
            selectionHandler.handleSelection(dataPoint, event.ctrlKey || event.metaKey);

            event.stopPropagation();
        });

        clearCatcher.on("click", () => {
            selectionHandler.handleClearSelection();
        });
    }

    public renderSelection(hasSelection: boolean) {
        const {
            pointSelection,
            interactivityService,
        } = this.options;

        const hasHighlights: boolean = interactivityService.hasSelection();

        pointSelection.style("opacity", (dataPoint: StripPlotPoint) => {
            return getFillOpacity(
                dataPoint.selected,
                dataPoint.highlight,
                !dataPoint.highlight && hasSelection,
                !dataPoint.selected && hasHighlights,
            );
        });
    }
}

 

 

During the update of the Visual I am converting the dataView to my dataViewModel and adding the selectionIds:

 

 

           let dataPoints: StripPlotPoint[] = [];
            for (let n = 0; n < dataView.matrix.rows.root.children.length; n++) {


                const selector: ISelectionId = host.createSelectionIdBuilder()
                .withMatrixNode(dataView.matrix.rows.root.children[n],dataView.matrix.rows.levels )   
                    .createSelectionId();
                let dataPoint: StripPlotPoint = {
                    category: dataView.matrix.rows.root.children[n].levelValues[categoryIndex].value,
                    value: dataView.matrix.rows.root.children[n].levelValues[valueIndex].value,
                    selected: false,
                    highlight: false,
                    identity: selector,
                    opacity: 1,
                    hasHighlights: false
                }
                dataPoints.push(dataPoint)

            }

 

 When checking the datapoints I can see that there are values added for the identity (see screenshot of my console.log)

Screenshot 2020-07-24 at 15.49.59.png

 

 

In the development-visual the data the dataview looks like (i removed a lot of children to limit the size)

 

[
	{
		"metadata":{
			"columns":[
				{
					"roles":{"category":true},
					"type":{"underlyingType":1,"category":{},"primitiveType":1,"extendedType":1,"categoryString":{},"text":true,"numeric":false,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},
					"displayName":"gender",
					"queryName":"strip-plot-test.gender",
					"expr":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","variable":"s","kind":0},"ref":"gender","kind":2},
					"rolesIndex":{"category":[0]},
					"index":0,
					"identityExprs":[{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"gender","kind":2}]
				},{
					"roles":{"value":true},
					"type":{"underlyingType":259,"category":{},"primitiveType":3,"extendedType":259,"categoryString":{},"text":false,"numeric":true,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},
					"displayName":"height",
					"queryName":"strip-plot-test.height",
					"expr":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","variable":"s","kind":0},"ref":"height","kind":2},
					"rolesIndex":{"value":[0]},
					"index":1,
					"identityExprs":[{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"height","kind":2}]}],
			"objects":{
				"chart":{"dataPointShape":"bar","showGridLines":true},
				"yAxis":{"textSize":19},
				"triangle":{"strokeWidth":0,"size":12},
				"license":{"show":true},
				"bar":{"strokeWidth":8,"size":9,"percentile":72}
			},
			"dataReduction":{
				"matrix":{"rows":{}}
			}
		},
		"matrix":{
			"rows":{
				"levels":[
					{
						"sources":[
							{
								"roles":{"category":true},
								"type":{"underlyingType":1,"category":{},"primitiveType":1,"extendedType":1,"categoryString":{},"text":true,"numeric":false,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},
								"displayName":"gender",
								"queryName":"strip-plot-test.gender",
								"expr":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","variable":"s","kind":0},"ref":"gender","kind":2},
								"rolesIndex":{"category":[0]},
								"index":0,
								"identityExprs":[{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"gender","kind":2}]
							},
							{
								"roles":{"value":true},
								"type":{"underlyingType":259,"category":{},"primitiveType":3,"extendedType":259,"categoryString":{},"text":false,"numeric":true,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},
								"displayName":"height",
								"queryName":"strip-plot-test.height",
								"expr":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","variable":"s","kind":0},"ref":"height","kind":2},
								"rolesIndex":{"value":[0]},
								"index":1,
								"identityExprs":[{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"height","kind":2}]
							}
							]
					}
					],
				"root":{
					"children":[
						{
							"levelValues":[
								{
									"levelSourceIndex":0,
									"value":"female"
								},
								{
									"levelSourceIndex":1,
									"value":57.50321861
								}
							],
							"value":57.50321861,
							"levelSourceIndex":1,
							"level":0,
							"identity":{
								"kind":1,
								"_expr":{"_kind":8,"left":{"_kind":13,"comparison":0,"left":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"gender","kind":2},"right":{"_kind":17,"type":{"underlyingType":1,"category":{},"primitiveType":1,"extendedType":1,"categoryString":{},"text":true,"numeric":false,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},"value":"female","typeEncodedValue":"'female'","valueEncoded":"'female'","kind":17},"kind":13},"right":{"_kind":13,"comparison":0,"left":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"height","kind":2},"right":{"_kind":17,"type":{"underlyingType":259,"category":{},"primitiveType":3,"extendedType":259,"categoryString":{},"text":false,"numeric":true,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},"value":57.50321861,"typeEncodedValue":"57.50321861D","valueEncoded":"57.50321861D","kind":17},"kind":13},"kind":8},
								"_key":{"factoryMethod":{},"value":"{\"and\":{\"l\":{\"comp\":{\"k\":0,\"l\":{\"col\":{\"s\":{\"e\":\"strip-plot-test\"},\"r\":\"gender\"}},\"r\":{\"const\":{\"t\":1,\"v\":\"female\"}}}},\"r\":{\"comp\":{\"k\":0,\"l\":{\"col\":{\"s\":{\"e\":\"strip-plot-test\"},\"r\":\"height\"}},\"r\":{\"const\":{\"t\":3,\"v\":57.50321861}}}}}}"},
								"expr":{"_kind":8,"left":{"_kind":13,"comparison":0,"left":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"gender","kind":2},"right":{"_kind":17,"type":{"underlyingType":1,"category":{},"primitiveType":1,"extendedType":1,"categoryString":{},"text":true,"numeric":false,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},"value":"female","typeEncodedValue":"'female'","valueEncoded":"'female'","kind":17},"kind":13},"right":{"_kind":13,"comparison":0,"left":{"_kind":2,"source":{"_kind":0,"entity":"strip-plot-test","kind":0},"ref":"height","kind":2},"right":{"_kind":17,"type":{"underlyingType":259,"category":{},"primitiveType":3,"extendedType":259,"categoryString":{},"text":false,"numeric":true,"integer":false,"bool":false,"dateTime":false,"duration":false,"binary":false,"none":false},"value":57.50321861,"typeEncodedValue":"57.50321861D","valueEncoded":"57.50321861D","kind":17},"kind":13},"kind":8},"key":"{\"and\":{\"l\":{\"comp\":{\"k\":0,\"l\":{\"col\":{\"s\":{\"e\":\"strip-plot-test\"},\"r\":\"gender\"}},\"r\":{\"const\":{\"t\":1,\"v\":\"female\"}}}},\"r\":{\"comp\":{\"k\":0,\"l\":{\"col\":{\"s\":{\"e\":\"strip-plot-test\"},\"r\":\"height\"}},\"r\":{\"const\":{\"t\":3,\"v\":57.50321861}}}}}}"}
						},
						{
							"levelValues":[
								{
									"levelSourceIndex":0,
									"value":"female"
								},
								{
									"levelSourceIndex":1,
									"value":57.97290083
								}
							]
						},...
					]
				},
				"columns":{
					"levels":[],
					"root":{
						"children":[]
					}
				},
				"valueSources":[]
			},
		"categorical":{},
		"table":{},
		"tree":{},
		"single":{}
	}
]

 

 

 

1 ACCEPTED SOLUTION
paul-maessen
Resolver I
Resolver I

Hi All,

 

It looks like this only works when you are not selecting Don't Summarize for the GroupingOrMeasure-datafield.

When you select an aggregation (it will behave like a measure) then the highlights do appear.

 

Unfortunately this is not going to work for this visual because of the granularity of the values. I need all values and not the aggregates.  So the hightlighting will work for the matrix-dataViewMapping when you select an aggregation for the measure

 

Regards

Paul

View solution in original post

1 REPLY 1
paul-maessen
Resolver I
Resolver I

Hi All,

 

It looks like this only works when you are not selecting Don't Summarize for the GroupingOrMeasure-datafield.

When you select an aggregation (it will behave like a measure) then the highlights do appear.

 

Unfortunately this is not going to work for this visual because of the granularity of the values. I need all values and not the aggregates.  So the hightlighting will work for the matrix-dataViewMapping when you select an aggregation for the measure

 

Regards

Paul

Helpful resources

Announcements
June 2022 update 768X460.jpg

Check it out!

Click here to read more about the June 2022 updates!

Power Platform Conf 2022 768x460.jpg

Join us for Microsoft Power Platform Conference

The first Microsoft-sponsored Power Platform Conference is coming in September. 100+ speakers, 150+ sessions, and what's new and next for Power Platform.

Power BI Dev Camp Session 23 768x460.jpg

Check it Out!

Mark your calendars and join us on Thursday, June 30 at 11a PDT for a great session with Ted Pattison!

June 20 episode 7 with aka link 768x460.jpg

The Power BI Community Show

Join us on June 20 at 11 am PDT when Kim Manis shares the latest on Azure Synapse analytics, the Microsoft Intelligent Data Platform, and notable Power BI Updates from Microsoft Build 2022.