Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
paul-maessen
Resolver I
Resolver I

Selection issue in combination with Highlighting

Hi All,

 

I am creating a custom visual and implemented Selection and Highlighting successfully.

Unfortunately I still have one strange behavior:

 

When I select a datapoint after highlighting one or more datapoints in my visual it does not select the datapoint, but does reset the selection.

 

I have created some screen-shots to show you the issue.

In the first picture below you can see three visuals:

  • Top Right : "my custom visual"
  • Top Left: Table
  • Bottom Right: Clustered Column Chart

HS_Issue_1.png

 In the second picture I selected the Pens-category in the table and these are highlighted in both other visuals.

HS_Issue_2.png

So far so good...

In the third picture you can see the result when I select in my Visual the Envelopes-datapoint:

HS_Issue_3.png

This is still the expected behavior... 

When I now click on the Paper-bar in the Clustered Bar Chart-visual to select this category I get the following result:

HS_Issue_4.png

 As you can see the Table-visual and the My Visual show the wrong result, In my Visual the Paper-catagory should be highlighted and in the table visual this categroy should be selected...

 

After some debugging I found out that the following happens when I select a datapoint in my Visual:

 

<edited the behavior after additional debugging>

In my debug-data I can see that the visual receives an update (type: 2). This seems to be right because the data is changed (highlights are added) and in my conversion from dataView to dataModel I get the correct settings for each dataPoint. However, I do get a second update immediately (again type 2) and I noticed that in the dataView the highlights are missing so that's why the visual is rendered without any highlight...

 

 

 

Below I have added the following code-parts:

 

behavior.ts

 

 

 

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 { ColumnPoint } from "./dataInterfaces";
import { IBehaviorOptions } from "powerbi-visuals-utils-interactivityutils/lib/interactivityBaseService";
import { LollipopColumnSettings } from "./settings";

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

const getEvent = () => d3.event;

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



export interface BehaviorOptions extends IBehaviorOptions<ColumnPoint> {
    clearCatcher: Selection<any>;
    pointSelection: Selection<ColumnPoint>;
    interactivityService: IInteractivityService<ColumnPoint>;
    settings: ColumnSettings;
    contextSelection: Selection<any>;
}

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: ColumnPoint) => {
            const event: MouseEvent = d3.event;
            selectionHandler.handleSelection(dataPoint, event.ctrlKey || event.metaKey);

            event.stopPropagation();
        });

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

    public renderSelection(hasSelection: boolean) {
        const {
            pointSelection,
            interactivityService
        } = this.options;
    
        pointSelection.style("opacity", (dataPoint: ColumnPoint) => {
            return getFillOpacity(
                dataPoint.selected,
                dataPoint.highlight,
                hasSelection ,
                dataPoint.hasHighlights
            );
        });

    }
}

 

 

 

 

In my visual.ts I have the following code regarding the interactivityService:

I imported the following:

 

 

import { interactivityBaseService as interactivityService, interactivitySelectionService } from "powerbi-visuals-utils-interactivityutils";

import { Behavior, BehaviorOptions } from "./behavior";

 

 

In the Visual-class I added the following variables:

 

 

private interactivityService: IInteractivityService<ColumnPoint>;
private behavior: Behavior

 

 

 

In the constructor I defined:

 

 

this.behavior = new Behavior();
this.interactivityService = createInteractivitySelectionService(this.host);

 

 

 

In the Update-method ( at the end) I defined the following code after I do render the chart:

 

 

            this.clearCatcher = appendClearCatcher(this.ColumnSvg.selectAll(".data-lines"));

            if (this.interactivityService) {
                const behaviorOptions: BehaviorOptions = {
                    clearCatcher: this.clearCatcher,
                    pointSelection: this.ColumnSvg.select(".data-points").selectAll("circle"),
                    interactivityService: this.interactivityService,
                    behavior: this.behavior,
                    dataPoints: this.viewModel.dataPoints,
                    settings: this.viewModel.settings,
                    contextSelection: this.ColumnSvg
                };

                this.interactivityService.bind(behaviorOptions);
                this.behavior.renderSelection(this.interactivityService.hasSelection());
            }

 

 

 

I am not sure if it is right to use "this.interactivityService.hasSelection()" to fill the hasSelection-param of the renderSelection-function.

 

Has some one had the same behavior as I describe above or can some one tell me what I am doing wrong?  Thanks in advance!

 

Regards

 

Paul

 

1 REPLY 1
paul-maessen
Resolver I
Resolver I

To clarify the issue above I created a GIF that does show the problem:

 

select-highlight-issue.gif

 

I hope this gives a better impression what is happening.

 

Thanks in advance!

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.