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

Get certified in Microsoft Fabric—for free! For a limited time, get a free DP-600 exam voucher to use by the end of 2024. Register now

Reply
Anonymous
Not applicable

private svg: d3.Selection<SVGElement>; in d3.v4

Hello,

For my other js dependencies I need d3.v4.

I tried to install newest version (npm ) and types.

But as I try to create svg element for d3.Selection I get the following error:  error TYPESCRIPT /src/visual.ts : (34,22) Generic type 'Selection<GElement, Datum, PElement, PDatum>' requires 4 type argument(s).

I tried to follow the instruction in this post: https://community.powerbi.com/t5/Developer/Setting-up-D3-V4-with-Custom-Visuals-and-Types/m-p/330101... but it did not seem to help. 

How can I get it work?

Many thanks in advance !!!

 

 

 

1 ACCEPTED SOLUTION
v-viig
Community Champion
Community Champion

Hi @Anonymous,

 

Could you please share all of files including package.json, pbiviz.json, and other files?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

View solution in original post

14 REPLIES 14
Anonymous
Not applicable

I'm currently trying to change

 

d3.Selection<SVGElement>
 
into
 
d3.Selection<SVGElement,any,any,any>
 
it seems to help, but I cannot fully test it, since I also have other problems in my code. 
v-viig
Community Champion
Community Champion

d3.Selection<SVGElement,any,any,any> is supposed to work well.

 

Please resolve other issues to make sure everything is working well.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Anonymous
Not applicable

Well it works. Kind of...

 

I've followed the steps in https://microsoft.github.io/PowerBI-visuals/docs/how-to-guide/migrating-to-powerbi-visuals-tools-3-0..., with the extra note: 

 

npm install powerbi-visuals-tools@beta -g

found in https://community.powerbi.com/t5/Developer/Custom-Visual-Setup-Exceptions-pbi-visuals-api-2-2-2-pbi-...

 

I was unable to just upgrade my project, so I started a new one, and move in the functions one by one. Some work, some don't. I'm now trying to get the circlecard to work. It compiles and runs, but it only shows the lower half of the circle.

 

Here is the semi-working code:

 

"use strict";
import "@babel/polyfill";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
import VisualObjectInstance = powerbi.VisualObjectInstance;
import DataView = powerbi.DataView;
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;
import * as d3 from "d3";

import { VisualSettings } from "./settings";
export class Visual implements IVisual {
    private target: HTMLElement;
    private settings: VisualSettings;

    //default:
    //private updateCount: number;
    //private textNode: Text;

    //circlecard:
    private svg: d3.Selection<SVGElement,any,any,any>;
    private container: d3.Selection<SVGElement,any,any,any>;
    private circle: d3.Selection<SVGElement,any,any,any>;
    private textValue: d3.Selection<SVGElement,any,any,any>;
    private textLabel: d3.Selection<SVGElement,any,any,any>; 

    constructor(options: VisualConstructorOptions) {

        //default:
        //console.log('Visual constructor', options);
        //this.target = options.element;
        //this.updateCount = 0;
        //if (typeof document !== "undefined") {
        //    const new_p: HTMLElement = document.createElement("p");
        //    new_p.appendChild(document.createTextNode("Update count:"));
        //    const new_em: HTMLElement = document.createElement("em");
        //    this.textNode = document.createTextNode(this.updateCount.toString());
        //    new_em.appendChild(this.textNode);
        //    new_p.appendChild(new_em);
        //    this.target.appendChild(new_p);
        //}

        //circlecard:
        this.target = options.element;
        const new_p: HTMLElement = document.createElement("p");
        this.target.appendChild(new_p);

        this.svg = d3.select(new_p)
            .append('svg')
            .classed('circleCard', true);
        this.container = this.svg.append("g")
            .classed('container', true);
        this.circle = this.container.append("circle")
            .classed('circle', true);
        this.textValue = this.container.append("text")
            .classed("textValue", true);
        this.textLabel = this.container.append("text")
            .classed("textLabel", true);


    }

    public update(options: VisualUpdateOptions) {
       
        //default:
        //this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
        //console.log('Visual update', options);
        //if (typeof this.textNode !== "undefined") {
        //    this.textNode.textContent = (this.updateCount++).toString();
        //}

        //circlecard:
        let width: number = options.viewport.width;
        let height: number = options.viewport.height;
        this.svg.attr("width", width)
            .attr("height", "height");
        let radius: number = Math.min(width, height) / 2.2;
        this.circle
            .style("fill", "white")
            .style("fill-opacity", 0.5)
            .style("stroke", "black")
            .style("stroke-width", 2)
            .attr("r", radius)
            .attr("cx", width / 2)
            .attr("cy:", height / 2);
        let fontSizeValue: number = Math.min(width, height) / 5;
        this.textValue
            .text("Value") 
            .attr("x", "50%")
            .attr("y", "50%")
            .attr("dy", "0.35em")
            .attr("text-anchor", "middle")
            .style("font-size", fontSizeValue + "px");
        let fontSizeLabel: number = fontSizeValue / 4;
        this.textLabel
            .text("Label")
            .attr("x", "50%")
            .attr("y", height / 2)
            .attr("dy", fontSizeValue / 1.2)
            .attr("text-anchor", "middle")
            .style("font-size", fontSizeLabel + "px");
  
    }

}

 

Anonymous
Not applicable

Ok, it works. There was a small bug (a colon where there shouldn't be one). 

 

So just use d3.Selection<SVGElement,any,any,any> and it should work fine. 

 

"use strict";
import "@babel/polyfill";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
import VisualObjectInstance = powerbi.VisualObjectInstance;
import DataView = powerbi.DataView;
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;
import * as d3 from "d3";

import { VisualSettings } from "./settings";
export class Visual implements IVisual {
    private target: HTMLElement;
    private settings: VisualSettings;

    //default:
    //private updateCount: number;
    //private textNode: Text;

    //circlecard:
    private svg: d3.Selection<SVGElement,any,any,any>;
    private container: d3.Selection<SVGElement,any,any,any>;
    private circle: d3.Selection<SVGElement,any,any,any>;
    private textValue: d3.Selection<SVGElement,any,any,any>;
    private textLabel: d3.Selection<SVGElement,any,any,any>; 

    constructor(options: VisualConstructorOptions) {

        //default:
        //console.log('Visual constructor', options);
        //this.target = options.element;
        //this.updateCount = 0;
        //if (typeof document !== "undefined") {
        //    const new_p: HTMLElement = document.createElement("p");
        //    new_p.appendChild(document.createTextNode("Update count:"));
        //    const new_em: HTMLElement = document.createElement("em");
        //    this.textNode = document.createTextNode(this.updateCount.toString());
        //    new_em.appendChild(this.textNode);
        //    new_p.appendChild(new_em);
        //    this.target.appendChild(new_p);
        //}

        //circlecard:
        this.target = options.element;
        const new_p: HTMLElement = document.createElement("p");
        this.target.appendChild(new_p);

        this.svg = d3.select(new_p)
            .append('svg')
            .classed('circleCard', true);
        this.container = this.svg.append("g")
            .classed('container', true);
        this.circle = this.container.append("circle")
            .classed('circle', true);
        this.textValue = this.container.append("text")
            .classed("textValue", true);
        this.textLabel = this.container.append("text")
            .classed("textLabel", true);


    }

    public update(options: VisualUpdateOptions) {
       
        //default:
        //this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
        //console.log('Visual update', options);
        //if (typeof this.textNode !== "undefined") {
        //    this.textNode.textContent = (this.updateCount++).toString();
        //}

        //circlecard:
        let width: number = options.viewport.width;
        let height: number = options.viewport.height;
        this.svg.attr("width", width)
            .attr("height", "height");
        let radius: number = Math.min(width, height) / 2.2;
        this.circle
            .style("fill", "white")
            .style("fill-opacity", 0.5)
            .style("stroke", "black")
            .style("stroke-width", 2)
            .attr("r", radius)
            .attr("cx", width / 2)
            .attr("cy", height / 2);
        let fontSizeValue: number = Math.min(width, height) / 5;
        this.textValue
            .text("Value") 
            .attr("x", "50%")
            .attr("y", "50%")
            .attr("dy", "0.35em")
            .attr("text-anchor", "middle")
            .style("font-size", fontSizeValue + "px");
        let fontSizeLabel: number = fontSizeValue / 4;
        this.textLabel
            .text("Label")
            .attr("x", "50%")
            .attr("y", height / 2)
            .attr("dy", fontSizeValue / 1.2)
            .attr("text-anchor", "middle")
            .style("font-size", fontSizeLabel + "px");
  
    }

}

 

Anonymous
Not applicable

I did find the solution for the part of the problem. 

module powerbi.extensibility.visual {
    "use strict";
    export class Visual implements IVisual {
        private target: HTMLElement;
        private updateCount: number;
        private settings: VisualSettings;
        private textNode: Text;
        private svg: d3.Selection<d3.BaseType, any, HTMLElement, any>;

        constructor(options: VisualConstructorOptions) {
            console.log('Visual constructor', options);
            this.target = options.element;
            this.svg = d3.select<SVGElement, any>(options.element as any)
            .append('svg')
            .classed('graph', true);
        }

        public update(options: VisualUpdateOptions) {
            this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
            // Set up an SVG group so that we can translate the final graph.
            let svg = d3.select("svg");
            let inner = svg.append("g");

            // Create a new directed graph
             var g = new dagreD3.graphlib.Graph();
                g.setGraph({});

                // Fill node "A" with the color green
            g.setNode("A", { style: "fill: #afa" });

            // Create the renderer
            var render = new dagreD3.render();

            // Run the renderer. This is what draws the final graph.
            //render(inner, g);
              //  inner.call(render,g);
            render(inner, g);


        }

I put the 

private svg: d3.Selection<d3.BaseType, any, HTMLElement, any> as described here: https://community.powerbi.com/t5/Developer/Error-Custom-Visual/m-p/219802
But as I try to save and build the visual I get the following error :  error TYPESCRIPT /src/visual.ts : (63,20) Argument of type 'Selection<BaseType, {}, HTMLElement, any>' is not assignable to parameter of type 'Selection<any>'.
Property 'length' is missing in type 'Selection<BaseType, {}, HTMLElement, any>'.
The error comes from render(inner, g); and says that I cannot assign any type to the "inner" parameter.
How can I loose it ???
Many thanks in advance.
 
v-viig
Community Champion
Community Champion

What arguments the render accepts? Can you sahre the whole source code?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Anonymous
Not applicable

Hi v-viig,

 

Thank you for your answer. What I am trying to do is rendering Dagre Graph with D3 (actually Dagre-D3). Inside of Javascript I have no problems with rendering at all. I tried it with D3.V3 but it does not render my graph and I do not get any errros. So I thought I would give it a try in D3.V4. I have following dependencies in my pbiviz.json: 

  "externalJS": [
    "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js",
    "node_modules/d3/build/d3.min.js",
    "node_modules/graphlib/dist/graphlib.core.js",
    "node_modules/dagre/dist/dagre.core.js",
    "node_modules/dagre-d3/dist/dagre-d3.min.js"

  ],

I did npm install and @types install for all the files (newest version). My visuals.ts looks as follows: 

/*
 *  Power BI Visual CLI
 *
 *  Copyright (c) Microsoft Corporation
 *  All rights reserved.
 *  MIT License
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the ""Software""), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */

module powerbi.extensibility.visual {
    "use strict";
    export class Visual implements IVisual {
        private target: HTMLElement;
        private updateCount: number;
        private settings: VisualSettings;
        private textNode: Text;
        private svg: d3.Selection<d3.BaseType, any, HTMLElement, any>;

        constructor(options: VisualConstructorOptions) {
            console.log('Visual constructor', options);
            this.target = options.element;
            this.svg = d3.select<SVGElement, any>(options.element as any)
            .append('svg')
            .classed('graph', true);
        }

        public update(options: VisualUpdateOptions) {
            this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
            // Set up an SVG group so that we can translate the final graph.
            let svg = d3.select("svg");
            let inner = svg.append("g");

            // Create a new directed graph
             var g = new dagreD3.graphlib.Graph();
                g.setGraph({});

                // Fill node "A" with the color green
            g.setNode("A", { style: "fill: #afa" });

            // Create the renderer
            var render = new dagreD3.render();

            // Run the renderer. This is what draws the final graph.
            render(inner, g);

        }

        private static parseSettings(dataView: DataView): VisualSettings {
            return VisualSettings.parse(dataView) as VisualSettings;
        }

        /** 
         * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the 
         * objects and properties you want to expose to the users in the property pane.
         * 
         */
        public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
            return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
        }
    }
}

The error message that I get: [ts]
Das Argument vom Typ "Render" kann dem Parameter vom Typ "(selection: Selection<BaseType, {}, HTMLElement, any>, ...args: any[]) => void" nicht zugewiesen werden.
Die Typen der Parameter "selection" und "selection" sind nicht kompatibel.
Der Typ "Selection<BaseType, {}, HTMLElement, any>" kann dem Typ "Selection<any>" nicht zugewiesen werden.
Die Eigenschaft "length" fehlt im Typ "Selection<BaseType, {}, HTMLElement, any>".

 

So it should some kind of length parameter haben. But I do not see where should it come from.

Can you help me further with that ? I could send you the whole package but the forum does not seem to be the right place.

 

Best regargs,

 

feelfine

v-viig
Community Champion
Community Champion

Hi @Anonymous,

 

Could you please share all of files including package.json, pbiviz.json, and other files?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Hi @Anonymous and @v-viig

 

Is this issue still not fixed?

We have not received whole source code to investigate this issue yet.

 

If you have similar issues please send us source code for investigating.

If you found a solution please post it here.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Hi @v-viig, Thanks for your reply.

I have worked on d3 but this is the first time, I am trying dagre-d3. In Angular 5 application, I was exploring with arrows.html (we can take any other html) sample provided in https://github.com/dagrejs/dagre-d3/tree/master/demo.

On render method, i.e. render(inner, g); I am getting the same error mentioned above by @Anonymous. 

i.e.

Argument of type 'Selection<BaseType, {}, HTMLElement, any>' is not assignable to parameter of type 'Selection<any>'.
Property 'length' is missing in type 'Selection<BaseType, {}, HTMLElement, any>'.

I have installed 5.5.0 version of d3 and 0.6.1 version dagre-d3. The same error I am getting on React application. Not sure if there is any breaking change in dagre-d3 version.

 

These issues come from TypeScript. Could you please share what type definitions you installed?

Can you share source code to check it from our end?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

hi @v-viig

 

You are right, even I found the same thing yesterday, the type defination was causing the issue.  Any version of 4 or 5 of @types/d3 has different signature of d3 select method than that of what dagre-d3 expects. If we switch back to verion 3 of d3, it solves that issue. For the moment I have uninsalled the @types/d3 and it is working fine now.

For detail, the issue was, the version 4 or 5 of d3 expects the return type of select method as Selection<BaseType, {}, HTMLElement, any> but dagre-d3 render method expects first parameter of type Selection<any>. In version 3 of @types/d3, the return type is Selection<any>, so it works fine with all the V3 versions.

I have to write a method which will do that typecasting, incase I want to use the defination file for other features.

 

Thanks

Sameer

Before using type casting please make sure dagre-d3 supports this d3 version well.

Since d3v3 and d3v4 are not compatible such type casting might produce compatibility issue on JavaScript level.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Helpful resources

Announcements
November Carousel

Fabric Community Update - November 2024

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

Live Sessions with Fabric DB

Be one of the first to start using Fabric Databases

Starting December 3, join live sessions with database experts and the Fabric product team to learn just how easy it is to get started.

Las Vegas 2025

Join us at the Microsoft Fabric Community Conference

March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount! Early Bird pricing ends December 9th.

Nov PBI Update Carousel

Power BI Monthly Update - November 2024

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