cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
rnenninger Frequent Visitor
Frequent Visitor

Custom Visual is empty when pinned to Dashboard

I created a custom visualization similar to the Card but only displaying the most recent value.

 

I can see the control working as expected at the report level, but when I pin the visual to a dashboard it's empty. I confirmed the

"Export Data" option returns the data.

 

Any idea why is not showing up?

Thanks!

 

Code:

module powerbi.visuals {
    export interface CardStreamData {
        dataPoints: CardStreamDataPoint[];    
    };

    export interface CardStreamDataPoint{
        dayDateTime: Date;
        value: number;
    }

    export class ControlTest implements IVisual {

        public static capabilities: VisualCapabilities = {
            dataRoles: [
                {  
                    name: 'Series',
                  kind: VisualDataRoleKind.Grouping,
                  displayName: 'Series'
                },{
                    name: 'Values',
                    kind: VisualDataRoleKind.Measure,
                    displayName: 'Value'
                }
            ],
            objects: {
               general: {
                    properties: {
                        formatString: {
                            type: { formatting: { formatString: true } },
                        }
                    }
               } 
            },
            dataViewMappings:[{
                conditions: [
                    { 'Series':{min:1, max:1}, 'Values': { max: 1 } }
                ],
                categorical: {
                    values: {
                        group:{
                            by: 'Series',
                            select: [{ for: {in: 'Values'} }],
                            dataReductionAlgorithm: { bottom : {} }
                        }
                    }
                }
            }] 
        };

        private static VisualClassName = 'controlTest';
        private static Layer: ClassAndSelector = {
            class: 'layer',
            selector : '.layer'
        };

        private element: JQuery;
        private dataView: DataView;

        private value = 0;

        public static converter(dataView: DataView): CardStreamData {
            var dataPoints = [];

            if (dataView && dataView.categorical && dataView.categorical.values)
            {
                var values = dataView.categorical.values;

                for (var i = 0, iLen = values.length; i < iLen; i++){
                    var timestamp : Date = new Date(values[i].source.groupName);

                    // todo: add property to manage number of decimals
                    var sourceValue: number = values[i].values[0].toFixed(2);
                    var entry : CardStreamDataPoint = {
                        dayDateTime: timestamp,
                        value: sourceValue
                    }

                    dataPoints.push(entry);
                }

            }

            return {
                dataPoints: dataPoints
            }

            //commented so I can return hard-coded data for testing
            /*return {
                dataPoints: [{dayDateTime:new Date(2016, 0, 1, 1, 10, 0), value: 5.6},
                    {dayDateTime:new Date(2016, 0, 3, 1, 10, 0), value: 5.2} 
                    ,{dayDateTime:new Date(2016, 0, 2, 1, 10, 0), value: 5.1}
                    ,{dayDateTime:new Date(2016, 0, 6, 1, 11, 0), value: 5.66}
                    ,{dayDateTime:new Date(2016, 0, 5, 1, 10, 0), value: 5.5}
                    ,{dayDateTime:new Date(2016, 0, 4, 1, 10, 0), value: 5.4}]
            }*/
        }

        private getPropertyByName(dataView: DataView, propertyName: string){
            if (dataView){
                var objects = dataView.metadata.objects;
                if (objects){
                    var general = objects['general'];
                    if (general) {
                        return <string>general[propertyName];
                    }
                }
            }
        }

        public init(options: VisualInitOptions): void {
            this.element = options.element;
            var element = options.element;

            // hard coded styling for now...
            // todo: add format, aligment properties
            this.element.text(this.value).css('font-size', '40px').css('font-weight', 'bold');   
        }

        public update(options: VisualUpdateOptions) {
            if (!options.dataViews || !options.dataViews[0]) return;

            var dataView = this.dataView = options.dataViews[0];
            var data = ControlTest.converter(dataView);
            var dataPoints = data.dataPoints;
            var viewport = options.viewport;

            // array sort 
            var sort_by = function(field, reverse, primer){

               var key = primer ? 
                   function(x) {return primer(x[field])} : 
                   function(x) {return x[field]};

               reverse = !reverse ? 1 : -1;

               return function (a, b) {
                   return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
                 } 
            }

            var sortedDataPoints = data.dataPoints.sort(sort_by('dayDateTime', true, function(a){return a}))
            //alert('' +sortedDataPoints[0].dayDateTime +'=>' + sortedDataPoints[0].value);

            // return the first entry of the sorted data points
            this.value = sortedDataPoints[0].value;            
            this.element.text(this.value);
        }
    }
}