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

July 7 - July 17 | Round 2 of the Power BI Dataviz World Championships. Don't miss your chance! Learn more

Reply
az2451
Resolver I
Resolver I

d3 v4 and selectionManager

I have updated my d3 library from v3 to v5 ([email protected])

 

Now im facing the consequences 🙂

 

I got everything working except for d3.selection

In the v3 this was the correct way to spell it:

private chartSelection: d3.selection.Update<ChartDataPoint>;
private svg: d3.Selection<SVGElement>;

But now since v4 it wants even more than that (by sudden, it wants 4 arguments!!)

 

Check it out:

 

Generic type 'Selection<GElement, Datum, PElement, PDatum>'

/* The first generic "GElement" refers to the type of the selected element(s).
The second generic "Datum" refers to the type of the datum of a selected element(s).
The third generic "PElement" refers to the type of the parent element(s) in the D3 selection.
The fourth generic "PDatum" refers to the type of the datum of the parent element(s).
A D3 Selection of elements. */

I dont get it how to use this masterpiece

 

Does anyone can help me here?

 

1 ACCEPTED SOLUTION
v-viig
Community Champion
Community Champion

It seems d3v4 handles selections in a different they in comparison to d3v3.

We'd recommend to take a look at this fixed version.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

[email protected]

View solution in original post

4 REPLIES 4
v-viig
Community Champion
Community Champion

We'd recommned to ask developer of d3 or d3 types about this issue.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

[email protected]

Alright, i have found out how d3 selections work:

 

private chartSelection: d3.Selection<d3.BaseType, ChartDataPoint, d3.BaseType, any>;
private svg: d3.Selection<SVGElement, {}, HTMLElement, any>;
private g: d3.Selection<SVGElement, {}, HTMLElement, any>;

But the problem seems to be something else because the syncSelectionState(): void 

dont work (no Errors are shown). That means i can not click on a specific datapoint.

 

It also seems to be that by installing the newest version of d3 ([email protected] @types/[email protected]) it also installed a different version of typescript (there is are new typescript folder in my node_modules). So the syntax changed a bit.

 

//For e.g. instead of 

this.svg.attr({
   width: width,
   height: height
});

//I now have to write it like this:

this.svg
   .attr('width', width)
   .attr('height', height);

 

 

However, the selectionIds actually exist for each datapoint (I can for e.g. change the color of each datapoint over formatting options)

 

this.datapoint.selectionId.getSelector()

I cant understand why the selectionManager wont work, where it should be working now.

 

Here is my whole code for download: MyGoogleDrive

 

 

Is there someone who is also using d3 v4  and managed to get selectionManager working?

I would be very thankful!

v-viig
Community Champion
Community Champion

It seems d3v4 handles selections in a different they in comparison to d3v3.

We'd recommend to take a look at this fixed version.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

[email protected]

Hi Ignat,

 

works fine for me.

 

Thank you very much!

 

For everyone who has the same issue follow these steps:

 

1. STEP: Change the selection datatype to the new d3 v4 format to something like this:

 

private chartSelection: d3.Selection<d3.BaseType, ChartDataPoint, d3.BaseType, any>; // Needed to display datapoints
private svg: d3.Selection<SVGElement, {}, HTMLElement, any>; // SVG-Element (Container)
private g: d3.Selection<SVGElement, {}, HTMLElement, any>; // SVG-Element (group 'g')

 

2. STEP: Add <SVGElement> when calling the constructor:

 

constructor(options: VisualConstructorOptions) {
			
            this.host = options.host;

            this.selectionManager = options.host.createSelectionManager();
            this.selectionManager.registerOnSelectCallback(() => {
                this.syncSelectionState(this.chartSelection, this.selectionManager.getSelectionIds() as ISelectionId[]);
            });

           
            this.svg = d3.select(options.element).append<SVGElement>('svg');
	    this.g = this.svg.append<SVGElement>('g');
            
}

3. STEP: When creating the datapoints, you have to add the d3 event directly to it. That means if your code look something similar like this:

 

            // Create a SVG-Element (datapoints)
            this.chartSelection = this.g
	         .append('g')
                 .selectAll('.dot')
                 .data(viewModel.dataPoints);

            this.chartSelection
                .enter()
                .append('circle')
                .attr('r', 5)
                .merge(this.chartSelection)
                .classed('dot', true)
                .attr('cx', d => x(<number>d.gesamtKosten))
                .attr('cy', d => y(<number>d.anzahlKostenstellen))
                .attr('fill', d => d.color);

this.syncSelectionState(
                this.chartSelection,
                this.selectionManager.getSelectionIds() as ISelectionId[]
            );

            this.chartSelection.on('click', (d) => {
                // Allow selection only if the visual is rendered in a view that supports interactivity (e.g. Report)
                if (this.host.allowInteractions) {
                    const isCrtlPressed: boolean = (d3.event as MouseEvent).ctrlKey;
                    this.selectionManager
                        .select(d.selectionId, isCrtlPressed)
                        .then((ids: ISelectionId[]) => {
                            this.syncSelectionState(this.chartSelection, ids);
                        });

                    (<Event>d3.event).stopPropagation();
                }
            });

            this.chartSelection
                .exit()
                .remove();

            // Clear selection when clicking outside a dot
            this.svg.on('click', (d) => {
                if (this.host.allowInteractions) {
                    this.selectionManager
                        .clear()
                        .then(() => {
                            this.syncSelectionState(this.chartSelection, []);
                        });
                }
            });

Change it to this:

 

                 // Create a SVG-Element (datapoints)
	         this.chartSelection = this.g
		     .append('g')
                     .selectAll('.dot')
                     .data(viewModel.dataPoints);

                this.chartSelection
                     .enter()
                     .append('circle')
                     .on('click', (d) => {
                       // Allow selection only if the visual is rendered in a view that supports interactivity (e.g. Report)
                       if (this.host.allowInteractions) {
                        const isCrtlPressed: boolean = (d3.event as MouseEvent).ctrlKey;
                        this.selectionManager
                            .select(d.selectionId, isCrtlPressed)
                            .then((ids: ISelectionId[]) => {
                                this.syncSelectionState(this.g.selectAll(".dot"), ids);
                            });
    
                        (<Event>d3.event).stopPropagation();
                    }
                })
                .attr('r', 5)
                .merge(this.chartSelection)
                .classed('dot', true)
                .attr('cx', d => x(<number>d.gesamtKosten))
                .attr('cy', d => y(<number>d.anzahlKostenstellen))
                .attr('fill', d => d.color);
this.syncSelectionState( this.g.selectAll(".dot"), this.selectionManager.getSelectionIds() as ISelectionId[] ); this.chartSelection .exit() .remove(); // Clear selection when clicking outside a dot this.svg.on('click', (d) => { if (this.host.allowInteractions) { this.selectionManager .clear() .then(() => { this.syncSelectionState(this.chartSelection, []); }); } });

4. STEP: Edit the syncSelectionState():

 

private syncSelectionState(
		
            selection: d3.Selection<d3.BaseType, any, d3.BaseType, any>,
            selectionIds: ISelectionId[]
			
): void { ... }

I hope this helps!

Helpful resources

Announcements
FabCon and SQLCon Barcelona 2026

FabCon & SQLCon – Barcelona 2026

Join us in Barcelona for FabCon and SQLCon, the Fabric, Power BI, SQL, and AI community event. Save €200 with code FABCMTY200.

60 days of Data Days Carousel

Data Days 2026

Join Fabric Data Days 2026: 60 days of free live/on-demand sessions, challenges, study groups, and certification opportunities.

Power BI DataViz World Championships carousel

Power BI DataViz World Championships - June 2026

A new Power BI DataViz World Championship is coming this June! Don't miss out on submitting your entry.

Top Solution Authors