Forum Discussion

sheetalshettiga's avatar
6 years ago
Solved

custom table visual

Hello, I am creating a custom visual as below, In the input column i give some numbers and it calculates the percantage as Totalsalescost/Input But in percentage column the result gets refle...
  • dm-p's avatar
    dm-p
    6 years ago

    Hi sheetalshettiga - it's a lot more helpful if you can paste your code as text rather than as a screengrab so that it's easier to copy into my dev environment 🙂

    Looks like you're using d3, so you can refer to the event handling documentation for more details, but there's not a lot of resource on how to do this, as it's not a common use case for d3 (particularly with TypeScript), so I've had to figure some of it out.

    Here's some working code with a single text element and a <p> element that proves we can update the value once we tab out of the box (so you will need to adapt to your code):

    This will fire once the elment is tabbed out of, so you might need to adapt for a different event type - but it will grab the element you typed into, get the value and pass it to the percent function (which I just stubbed out to display the message with the number interpolated; it would take me too long to manually type in your function code and I don't have your DOM anyway so it wouldn't work as intended).

    For reference, here's my code - I just created a blank visual and worked from there:

    /** Visual.ts */
    "use strict";
    
    import "core-js/stable";
    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;
    
        constructor(options: VisualConstructorOptions) {
            console.log('Visual constructor', options);
            this.target = options.element;
        }
    
        public update(options: VisualUpdateOptions) {
            this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
            console.log('Visual update', options);
    
            /** This is just a quick PoC */
                const container = d3.select(this.target);
                container.selectAll('*').remove();
                
                /** Simple test element to add output to */
                const display = container
                    .append('p')
                    .attr('id', 'myReplacedValue')
                    .text('Initial');
                
                /** input with initial value */
                const inp = container
                    .append('input')
                        .attr('type', 'text')
                        .attr('value', 0)
                        /** I'm doing as a fat arrow function so that 'this' is still the visual class */
                        .on('change', () => {
                            const
                                keyEvent: KeyboardEvent = <KeyboardEvent>d3.event,
                                eventTarget: EventTarget = keyEvent.target,
                                value = d3.select(<HTMLInputElement>eventTarget).node().value;
                            this.percent(Number.parseFloat(value));
                        });
        }
    
        private percent(n: number) {
            /** 
             *  This is a stub, to prove we can get and use the number from the box
             */
             d3.select('#myReplacedValue')
                .text(`The entered percentage was ${n}.`);
        }
    
        private static parseSettings(dataView: DataView): VisualSettings {
            return <VisualSettings>VisualSettings.parse(dataView);
        }
    
        /**
         * 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);
        }
    }

     

    If you need further assistance, this is more of a web development question rather than custom visuals specifically, so you might get more readily available assistance (and better than mine) on a wider forum more geared towards JavaScript and TypeScript in general, but I'm hoping that this may get you moving, and thanks for the question - it's not something I'd tried before 🙂

    Good luck!

    Daniel