Adding Simple Properties To Your Power BI Custom Visual

Posted by

Learn how to add simple properties to your Power BI Custom Visual. This is video #15 of the Power BI Custom Visual Development Fundamentals series, please check the playlist below for the set.

Playlist @ https://goo.gl/qbHDSq
Code @ https://goo.gl/7C4LeM
Dataset @ https://goo.gl/DEaZYY
D3 v3.x Docs @ https://goo.gl/xHZQ18

Transcript

Hello again and welcome back to this series on developing Power BI Custom Visuals.

Today you will learn how to add simple settings to the properties pane of your visual.

These properties allow the user to change certain aspects of your visual, such as font sizes and colours and whether you’re drawing puppies or kittens or whatever else you want really.

In this example, you will use them to hide and show the axis that you added in the previous video.

So let’s get to it, right now.

So the first thing is, we’re going to is install a new helper package via npm.

This is completely optional, but doing so will make our lives easier down the line.

The package in question is the power bi data view utilities package and like the name suggests, it contains a few utility classes that help us extract information out from the data views.

Before we install this though, we need to stop the pbiviz utility for a minute using control-c, then y.

Now we can run the npm command to install this package.

This is now installed so we just need to reference a couple of new files on the project configuration.

"node_modules/powerbi-visuals-utils-dataviewutils/lib/index.d.ts"

First get let’s go to the tsconfig project file and add the package’s typescript declaration file.

This file has no executable code if you check it, it just declares what types exist in the compiled code file.

Which is exactly what we’re going to add to the pbiviz file list.

So here we add the javascript file from the package that contains the compiled javascript code.

"node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js"

Now you will notice this pattern a lot when adding more and more packages.

This is not always the case, but a lot of times, developers package their final product onto two files.

One is a compiled and minified javascript file that you can use anywhere, regardless if you’re using typescript or any other javascript superset.

And the other one, in our case, is a typescript definition file that simply declares what new types can the typescript compiler assume to exist, so that you can use them in your typescript code while keeping the benefits of static typing.

Remember, static typing is a typescript thing, not a javascript one.

Anyway, we’ve added the new files so we can run the pbiviz utility again and see if everything works.

There you go, everything is still working.

Now let’s get those properties going.

Switch to Visual Studio Code, visual.ts

So the first thing we need to, is to go over to the capabilities.json file.

Again, this is where you tell Power BI what your visual can do.

"objects": {
},

We’re now going to add an entry called objects.

This entry will contain a list of all the custom properties in your visual, grouped by a property header.

        "xAxis": {
            "displayName": "X Axis",
            "properties": {
                "show": {
                    "displayName": "Show X Axis",
                    "type": { "bool": true }
                }
            }
        },

For starters, we’re going to add a property to the visual that allows the user to enable or disable the X Axis.

So there are a few elements to this.

The “xAxis” element refers to the internal name of the property group.

This is the identifier that we can use, when we want to access this property group in code.

And indeed, that’s something that we will do in just a minute.

The display name on the other hand is the label that the end-user sees for this property group.

You can put here whatever makes sense to show on the interface.

Now each property group can have one or more properties in it, and we define that group with this “properties” element.

For now, we will start with a single property to allow the user to enable or disable the X Axis.

As you can probably guess, this “show” is the internal identifier of that property.

Likewise the displayname is the visible label in the properties pane itself.

What is new here is the type of the property.

Depending on this type, Power BI will render the property differently on-screen and you can play around with this if you want.

For the show x-axis property, we’re defining it as a boolean.

This will mean we’re either showing the axis or not showing the axis, and for this Power BI will render a neat toggle button that you can just click on.

Now, just defining this property in the capabilities file does not make it show up in the properties pane.

Power BI instead uses this property list to later inquire your visual whether you actually want to display each property or keep them to yourself and if you do want to display a certain property, then what’s the current value for it that you want the user to see.

So we need to make these decisions in the visual instead.

Let’s go back to the visual code and look at the settings object we created in the last video.

This is where we defined some defaults for the border and padding.

We’re going to add some new settings to reflect the need for showing and hiding the axes but we’re going to make things a little different now.

        private settings = {
            axis: {
                x: {
                    padding: {
                        default: 50,
                        value: 50
                    },
                },
                y: {
                    padding: {
                        default: 50,
                        value: 50
                    }
                }
            },
            border: {
                top: {
                    default: 10,
                    value: 10
                }
            }
        }

Before that though, I’m going to refactor this code into something a bit more useful.

What I’m doing here is splitting each setting into a default value and a current value.

This simple pattern will let us assign new values to each setting without worrying about losing the defaults.

Now by doing this, we’ve broken the code miserably, so let’s go ahead and fix it.

There you go, all working now.

                   show: {
                        default: true,
                        value: true
                    }

Let’s get back to the settings object and add a new settings to show x the axis.

This will have a default value of true and a current value of true as well although this doesn’t matter very much, as we will update this value upon loading the visual.

However, before we can get a setting from the user, we have to expose these settings in the properties pane, so that the user can change them in the first place.

The Power BI API has a peculiar way of doing this.

        public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {

            return null;
        }

Let’s add a new function to the end of the visual code.

enumerateObjectInstances.

That’s a mouth full.

Now this fella is an API function that Power BI calls as if by magic, every single time it needs to display or update a property in the properties pane.

The driver for those calls is in fact, the list of property groups that we define in the capabilities.json file.

So what this mean is that, every single time Power BI needs to render the properties pane, it will go through your declared property groups in capabilities.json and then call this function one time per each of those property groups.

It then expects this function to return the list of properties that you actually want to display, along with their current values and any extra configuration, such as minimum as maximum value restrictions.

Now this whole thing happens outside of the update loop.

It’s perfectly possible to see the main update function running once and then see this function running as many times as needed to keep the properties pane updated.

So now that you know that, let’s add some code to this function.

            let propertyGroupName = options.objectName;
            let properties: VisualObjectInstance[] = [];

            switch (propertyGroupName) {
                case "xAxis":
                    properties.push({
                        objectName: propertyGroupName,
                        properties: {
                            show: this.settings.axis.x.show.value
                        },
                        selector: null
                    });
		break;
            };

            return properties;

So we’re doing a couple of things here.

As I said, this function gets called once per property group, so we need to check for what exact property group this function is getting called each time.

Then, based on that, we fill up this array of Visual Object Instances with the property information that we want to show to the user.

Right now, we only want to make one property visible and that’s the “show” property, so, we’re returning that, along with the current value of that property.

So this VisualObjectInstance array is literally the mini view model that Power BI uses to render those properties on-screen, in the properties pane.

We’re also setting this selector setting to null.

The selector setting relates to data bound properties, which is, by the way, the subject of the next video, but for now, leave it as null and don’t worry about it.

So let’s see what this did.

Okay, so we now have a new property group on the properties pane called X Axis.

We also have a new push slider here, which curiously is at the property group level, instead of being inside the property group.

This seems odd, but there is nothing wrong about this.

The properties pane has this convention, where, if the first property that you define is a boolean type and it’s called show, then, instead of popping inside the property group, it will in fact show in the header of the property and you when enable or disable it, it will automatically enable or disable all the other properties in the pane.

This is the same behaviour as all other properties you see in the visual pane.

This is a neat convention, which we happen to be using here as our first property is indeed a boolean called show.

This is all good, however our show property doesn’t seem to be working very well yet.

That’s because we are pushing the property value to the properties pane here, yet nowhere in our code are we getting the new value back from power bi when the user sets it.

So the way Power BI provides the new setting value to your visual, is by forcing an update every single time something changes and providing all the new property values in the metadata view.

This is cool as it means, you don’t have to worry about forcing updates yourself if anything changes, as power bi will just piggy back on the whole update cycle for you.

The only thing we need to do here then, is to improve our update function so it can read these settings as they become available.

So let’s get that done.

Let’s get back to the visual code.

import DataViewObjects = powerbi.extensibility.utils.dataview.DataViewObjects;

Now let’s add an import statement up top so we can use a helper object from that library we installed in the beginning of this video.

That package does not export its types by default so we need to import them on a case by case basis.

        private updateSettings(options: VisualUpdateOptions) {

        }

Now let’s go to the bottom and add a new function.

This updatesettings function will grab those new settings from the metadata as they come and update our internal settings object as appropriate.

            this.settings.axis.x.show.value = DataViewObjects.getValue(
                options.dataViews[0].metadata.objects, {
                    objectName: "xAxis",
                    propertyName: "show"
                },
                this.settings.axis.x.show.default);

To do that, we can use the DataViewObjects helper we just imported.

This helper does the grunt work of inspecting the metadata view for a specific property and then getting its value back for you.

And if the property is not there to begin with, it can also return a default value for you instead.

All that’s left is to wire this up in the update function.

this.updateSettings(options);

We’ll add this right in the top, so we’re sure that the settings are always up-to-date every time the update code runs.

So let’s see what this did.

And there you go, the property now holds its value.

So now that we have a working property to show or hide the X axis, we can go back to the code and make some use it.

let xAxisPadding = this.settings.axis.x.show.value ? this.settings.axis.x.padding.value : 0;

So what we’re going to do here, is to take into account both the show property and the internal padding setting, to decide whether to take into account the axis or not.

If the user wants to see the axis, we will retain the padding value.

If not, we use a padding of value of zero just for this update, which will make the axis render off-screen, while everything else will adapt like magic.

Now let’s replace all the uses of the x padding value from settings with this local variable instead.

Let’s see what this did.

And there you go, now the chart adapts accordingly.

Cool, isn’t it.

And that’s it, now you’ve learned how to add a simple property to let the user setup the visual to their own taste.

We’ll stop here today, but in the git hub code base you will also find another property for the y axis and additional properties to configure the borders of the visual as well.

Still, I do recommend you try to implement these by yourself using the steps you have learned today.

Anyway, if you have questions, let me know and I’ll get back to you.

In next video in this series, you will learn how to add data bound settings to the properties pane to let the user himself control the colours of the bars.

Until then, take care and see you next time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.