Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
8 years ago
Solved

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/highlight/true#M9775 but it did not seem to help. 

How can I get it work?

Many thanks in advance !!!

 

 

 

  • v-viig's avatar
    v-viig
    8 years ago

    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

    [email protected]

14 Replies

  • Anonymous's avatar
    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's avatar
      v-viig
      Icon for Community Champion rankCommunity Champion

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

       

      Ignat Vilesov,

      Software Engineer

       

      Microsoft Power BI Custom Visuals

      [email protected]

      • Anonymous's avatar
        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

  • Anonymous's avatar
    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's avatar
      v-viig
      Icon for Community Champion rankCommunity 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

      [email protected]

      • Anonymous's avatar
        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-visuals/td-p/576698

         

        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");
          
            }
        
        }