Quantcast
Channel: Developer topics
Viewing all articles
Browse latest Browse all 17878

Adding user parameters to an R powered visualization

$
0
0

I have an R powered visual to which I would like add  user parameters to change things like point color and weight for the plot.
As I have understood it, to do this I have to change the capabilities.json file and visual.ts

This is what i added in the capabilities.json

"objects": {
    "rcv_script": {
      "properties": {
        "provider": {
          "type": {
            "text": true
          }
        },
        "source": {
          "type": {
            "scripting": {
              "source": true
            }
          }
        }
      }
    },
	"settings_point_params": {
		"displayName": "Point aesthetics",
		"description": "Color and size",
		"properties":{
			"pointColor":{
				"displayName":"Point color",
				"description":"Point color",
				"type":{
					"fill":{
						"solid":{
							"color": true
						}
					}
				}
			},
			"weight":{
				"displayName":"Weight",
				"description":"Weight",
				"type":{
					"numeric":true
				}
			}
		}
	}
  }

And this is what I have in visual.ts

module powerbi.extensibility.visual {
    "use strict";
    // below is a snippet of a definition for an object which will contain the property values
    // selected by the users
    /*interface VisualSettings {
        lineColor: string;
    }*/

    // to allow this scenario you should first the following JSON definition to the capabilities.json file
    // under the "objects" property:
    // "settings": {
    //     "displayName": "Visual Settings",
    //     "description": "Visual Settings Tooltip",
    //     "properties": {
    //         "lineColor": {
    //         "displayName": "Line Color",
    //         "type": { "fill": { "solid": { "color": true }}}
    //         }
    //     }
    // }

    // powerbi.extensibility.utils.dataview
    import DataViewObjectsModule = powerbi.extensibility.utils.dataview.DataViewObject;

    // in order to improve the performance, one can update the <head> only in the initial rendering.
    // set to 'true' if you are using different packages to create the widgets
    const updateHTMLHead: boolean = false;
    const renderVisualUpdateType: number[] = [
        VisualUpdateType.Resize,
        VisualUpdateType.ResizeEnd,
        VisualUpdateType.Resize + VisualUpdateType.ResizeEnd
    ];


    //RVIZ_IN_PBI_GUIDE:BEGIN:Added to create HTML-based 
    interface VisualSettingsSplineParams {
        lineColor: string;
        conf1: string;
        conf2: string;
    }

    interface VisualSettingsPointParams {
        pointColor: string;
        weight: number;
    }

    interface VisualSettingsAxesParams {
        colLabel: string;
        textSize: number;
        scaleXformat: string;
        scaleYformat: string;
        sizeTicks: string;
        axisXisPercentage: boolean;
    }
    //RVIZ_IN_PBI_GUIDE:END:Added to create HTML-based 


    export class Visual implements IVisual {
        private rootElement: HTMLElement;
        private headNodes: Node[];
        private bodyNodes: Node[];
        private settings: VisualSettings;

        //RVIZ_IN_PBI_GUIDE:BEGIN:Added to create HTML-based 
        private settings_funnel: VisualSettingsSplineParams;
        private settings_point: VisualSettingsPointParams;
        private settings_axes: VisualSettingsAxesParams;
        //RVIZ_IN_PBI_GUIDE:END:Added to create HTML-based 

        public constructor(options: VisualConstructorOptions) {
            if (options && options.element) {
                this.rootElement = options.element;
            }
            this.headNodes = [];
            this.bodyNodes = [];

            //RVIZ_IN_PBI_GUIDE:BEGIN:Added to create HTML-based 
            this.settings_funnel = <VisualSettingsSplineParams>{

                lineColor: "blue",
                conf1: "0.95",
                conf2: "0.999"
            };

            this.settings_point = <VisualSettingsPointParams>{
                pointColor: "orange",
                weight: 1
            };

            this.settings_axes = <VisualSettingsAxesParams>{
                colLabel: "gray",
                textSize: 12,
                scaleXformat: "comma",
                scaleYformat: "none",
                sizeTicks: "8",
                axisXisPercentage: true
            };
            //RVIZ_IN_PBI_GUIDE:END:Added to create HTML-based 



        }

        public update(options: VisualUpdateOptions): void {

            if (!options ||
                !options.type ||
                !options.viewport ||
                !options.dataViews ||
                options.dataViews.length === 0 ||
                !options.dataViews[0]) {
                return;
            }
            const dataView: DataView = options.dataViews[0];
            this.settings = Visual.parseSettings(dataView);
            //RVIZ_IN_PBI_GUIDE:BEGIN:Added to create HTML-based 
            this.updateObjects(dataView.metadata.objects);
            //RVIZ_IN_PBI_GUIDE:END:Added to create HTML-based 
            let payloadBase64: string = null;
            if (dataView.scriptResult && dataView.scriptResult.payloadBase64) {
                payloadBase64 = dataView.scriptResult.payloadBase64;
            }

            if (renderVisualUpdateType.indexOf(options.type) === -1) {
                if (payloadBase64) {
                    this.injectCodeFromPayload(payloadBase64);
                }
            } else {
                this.onResizing(options.viewport);
            }
        }

        public onResizing(finalViewport: IViewport): void {
            /* add code to handle resizing of the view port */
        }

        private injectCodeFromPayload(payloadBase64: string): void {
            // inject HTML from payload, created in R
            // the code is injected to the 'head' and 'body' sections.
            // if the visual was already rendered, the previous DOM elements are cleared

            ResetInjector();

            if (!payloadBase64) {
                return;
            }

            // create 'virtual' HTML, so parsing is easier
            let el: HTMLHtmlElement = document.createElement("html");
            try {
                el.innerHTML = window.atob(payloadBase64);
            } catch (err) {
                return;
            }

            // if 'updateHTMLHead == false', then the code updates the header data only on the 1st rendering
            // this option allows loading and parsing of large and recurring scripts only once.
            if (updateHTMLHead || this.headNodes.length === 0) {
                while (this.headNodes.length > 0) {
                    let tempNode: Node = this.headNodes.pop();
                    document.head.removeChild(tempNode);
                }
                let headList: NodeListOf<HTMLHeadElement> = el.getElementsByTagName("head");
                if (headList && headList.length > 0) {
                    let head: HTMLHeadElement = headList[0];
                    this.headNodes = ParseElement(head, document.head);
                }
            }

            // update 'body' nodes, under the rootElement
            while (this.bodyNodes.length > 0) {
                let tempNode: Node = this.bodyNodes.pop();
                this.rootElement.removeChild(tempNode);
            }
            let bodyList: NodeListOf<HTMLBodyElement> = el.getElementsByTagName("body");
            if (bodyList && bodyList.length > 0) {
                let body: HTMLBodyElement = bodyList[0];
                this.bodyNodes = ParseElement(body, this.rootElement);
            }

            RunHTMLWidgetRenderer();
        }

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



        //RVIZ_IN_PBI_GUIDE:BEGIN:Added to create HTML-based 
        /**
         * This function gets called by the update function above. You should read the new values of the properties into 
         * your settings object so you can use the new value in the enumerateObjectInstances function below.
         * 
         * Below is a code snippet demonstrating how to expose a single property called "lineColor" from the object called "settings"
         * This object and property should be first defined in the capabilities.json file in the objects section.
         * In this code we get the property value from the objects (and have a default value in case the property is undefined)
         */
        public updateObjects(objects: DataViewObjects) {

            this.settings_funnel = <VisualSettingsSplineParams>{
                lineColor: DataViewObjectsModule.getValue<string>(objects, 'lineColor', 'blue'),
                conf1: DataViewObjectsModule.getValue<string>(objects, 'conf1', "0.95"),
                conf2: DataViewObjectsModule.getValue<string>(objects, 'conf2', "0.999")
            };

            this.settings_point = <VisualSettingsPointParams>{

                pointColor: DataViewObjectsModule.getValue<string>(objects, 'pointColor', 'orange'),
                weight: DataViewObjectsModule.getValue<number>(objects, 'weight', 1)
            };


            this.settings_axes = <VisualSettingsAxesParams>{


                colLabel: DataViewObjectsModule.getValue<string>(objects, 'colLabel', "gray"),
                textSize: DataViewObjectsModule.getValue<number>(objects, 'textSize', 12),
                scaleXformat: DataViewObjectsModule.getValue<string>(objects, 'scaleXformat', "comma"),
                scaleYformat: DataViewObjectsModule.getValue<string>(objects, 'scaleYformat', "none"),
                sizeTicks: DataViewObjectsModule.getValue<string>(objects, 'sizeTicks', "8"),
                axisXisPercentage: DataViewObjectsModule.getValue<boolean>(objects, 'axisXisPercentage', true)
            };

        }
        //RVIZ_IN_PBI_GUIDE:END:Added to create HTML-based 



        /** 
         * 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 {
            //RVIZ_IN_PBI_GUIDE:BEGIN:Added to create HTML-based 
            let objectName = options.objectName;
            let objectEnumeration = [];

            switch (objectName) {


                case 'settings_point_params':
                    objectEnumeration.push({
                        objectName: objectName,
                        properties: {
                            pointColor: this.settings_point.pointColor,
                            weight: this.settings_point.weight
                        },
                        selector: null
                    });
                    break;

            };


            //RVIZ_IN_PBI_GUIDE:END:Added to create HTML-based 

            return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
        }
    }
}

Supposedly, after doing this and packaging the visual I should see the new user parameters in Power BI desktop but that is not the case .. only the rcv_script shows up.
Is there something I'm missing?


Viewing all articles
Browse latest Browse all 17878

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>