Has it seriously been like… 6 or 7 weeks since the first installment? Geez. Somewhere along the way I got stupid busy with “real” work, and lost the time to write the blog. It happens. A Lot.
Anyway, in the previous article, I used the “built in” cloud experience for generating my custom visual (using that term pretty loosely, since it was the worst visual possible). The super low barrier to entry was fantastic. However, since then, the Power BI team have released a version of a new development environment… so we have to give that bad boy a try.
New Development Environment
Head on over to https://github.com/Microsoft/PowerBI-visuals for the full details.
The team has clearly been doing a bunch of work on the documentation – which is great! There are full directions for installing the environment, full source to a bar chart sample, etc. I did run into some issues trying to get my environment up and running… but I’m willing to guess/hope I had prior versions of dependencies (node.js, npm) causing me grief.
You certainly lose that “just go to a web page and start writing code” ease of use, but… I have to admit that it is a superior development environment. Plus check out the cute yellow power bi symbol… in ascii! 🙂
The way it works is that you will have a directory for each visual. You go into the directory and do a “pbiviz start” which causes node.js to start a local server rendering your visual… and also magically re-compiling every time the source changes. It works pretty cool in that you can edit a line of code, hit save, and click the cute refresh button in the UI and <poof> the visual is updated on pbi.com. Nice.
To test your visual, they added a new option on pbi.com at Settings / Developer / “Enable Developer Visual for Testing”… which adds a test visual to your available visuals, that magically connects back to your local visual being rendered out of node.js. It does seem indistinguishable from magic 🙂 The custom visual automatically adds a “Display Dataview” which is incredibly helpful (thanks dudes!).
What Changed?
Last time, we just used “test data” that was provided via the cloud-based development environment. There is probably still a way to do that, but… I am mentally prepared to render some actual data. I know, crazy right?
Minor note: I’m not really a front-end developer. I can kinda sorta mostly get by… doing a bit of CSS, a bit of javascript, and I’ve used some jQuery and thought it was pretty hot. However, in trying to understand how custom visuals work in power bi, I want to limit my external dependencies, which means I nuked my use of jQuery. I think the cool kids use D3 for similar purposes, but… I’m not one of the cool kids. Apparently there are folks trying to raise awareness about using too much jQuery? http://youmightnotneedjquery.com/
Other note: like any reasonable development environment… the source is split across a number of files. There are separate files/directories for your source, styles, assets, etc… and your capabilities now live in their own file as well. Nothing really unexpected or bad, but some minor changes compared when I was last writing my visual.
Other other note: Pretty sure there was a minor interface change to the IVisual as well… I don’t think there is an init() any longer… rather that work is done in a constructor. Fine. Whatever.
The View Model Issue
Now… every sample visual you will see… is going to do something intelligent. They are going to have a “ViewModel”. What is that? Not entirely sure… but it is probably related to MVC. 🙂 The idea is that you shouldn’t really render your visual directly based on the data coming out of Power BI’s dataview. Instead, you should have an interface (your ViewModel) that holds the data in a convenient format for your particular visual. If you are making a bar chart, you probably need all the {x,y} data points (category and value)… and probably “what is the max value” – so that you can “scale” your bars correctly. So, that data would makeup your ViewModel. If you are a map… you are probably going to want to store some latitude/longitude. etc. You then write a method to transform the dataview (coming from power bi) into your ViewModel… and then render your visual based on the ViewModel.
I have to say… I hate the way the power bi team handled this.
Not that they are “wrong”. On the contrary, they are totally right – the ViewModel abstraction absolutely makes your code/design cleaner, easier to maintain, easier to test, etc. MVC (and MVVM, etc) exist for very good reason! And I’m glad the team is using it. However…
My complaint is… it really has nothing to do w/ the requirements of creating a power bi visual. It’s a completely optional thing… a design decision to be left to the developer. But, the samples and documentation make this wildly unclear. I think you would naturally be left thinking “oh, I’m required to create this ViewModel thingy”. And… no… no you are not. That is simply how the samples decided to do it.
So, because I’m a rebel… I’m not using it.
Table Visual of Doom
Hope you weren’t expecting a “good” visual. I’m just going render an html table and see if I can style it or something. Oh hey! I found some code! Amazing!
public update(options: VisualUpdateOptions) {
var dataViews = options.dataViews;
if (!dataViews) return;
this.target.innerHTML = this.getTableHtml(dataViews[0]);
}
private getTableHtml(dataView: DataView): string {
var matrix = dataView.matrix;
if (!matrix) return;
var buffer = [];
buffer.push("<table class='ScottTable'>");
// Header columns
buffer.push("<th>");
for (var c = 0; c < matrix.columns.root.children.length; c++) {
buffer.push("<td>" + matrix.columns.root.children[c].value + "</td>");
}
buffer.push("</th>");
// All the rows...
for (var r = 0; r < matrix.rows.root.children.length; r++) {
// the "value" that put "on rows"
buffer.push("\n<tr><td>" + matrix.rows.root.children[r].value + "</td>");
// 1 measure value per column
var values = matrix.rows.root.children[r].values;
for (var key in values)
{
if (values[key].value)
buffer.push("<td>" + values[key].value + "</td>");
else
buffer.push("<td/>");
}
buffer.push("</tr>");
}
buffer.push("</table>");
return buffer.join("");
}
I think the only thing you “missed” is that in the constructor, I saved off the target div… in this.target. To read my data out of the dataview, you can see I’m reading the data out via the Matrix data… cuz hey, tables look kinda like Matrix’es (that’s the correct pluralization, I’m pretty sure).
Because I have no idea what I’m doing, and I didn’t want to learn D3 like the cool kids… I simply “push” text elements onto an array, then mash the text results together via array.join… and use that text to replace the innerHtml of my target element. It works.
Anybody actually following along and trying to create a visual… will really benefit from the built in debug option that shows you the dataview.
That way you can make sense of my matrix.rows.root.children[r].values… etc. Otherwise, that probably looks pretty gibberishy.
Notice I assigned a class to my table (the very aptly named ScottTable class)… making it easy to apply some CSS like Table.ScottTable td { blah blah blah }.
And indeed after some styling, you get this… um, kinda ugly and not completely totally 100% correct visual… over on the right! Woooo!
I totally cheated on my styling… as I’m not allowing the user to set the colors, font size, etc. And apparently… when power bi sends me “value” to stick into my table… they don’t magically come “pre-formatted”. Some learning to do there.
Under and to the left (cuz I couldn’t figure out how to add it to my blog post to the right…) you can see the built-in matrix visualization for comparison… notice the tiny font (which.. .uhh… they let you customize, unlike mine), but more importantly… the correct formatting of the data and the fancy Total. I have no idea how/where that total comes from – maybe the visual added it up?
Next Steps
While I didn’t show it here… in my “capabilities” I told Power BI that I have 3 places to drop stuff… { Rows, Columns, Values }. Of course, my code is too elementary to correctly handle anything but exactly 1 row, 1 column and 1 value… which is pretty lame. The built-in matrix visualization handles multiples just fine 🙂
So… theoretically I should fix that. Except, I don’t super care… this was just a learning exercise 🙂 There are a few things I would like to do:
- Have a bar chart that can handle multiple fields on the axis. Currently if you put (say) Year and Month fields… you can drill down… but I really want to just see Year and Month on axis. And apparently I’m too lazy to add a new calc column with Year and Month in 1 field. 🙂 Native excel handles this the way I like… 🙁
- There are a LOT of visualization libraries out there. Google charts, Plotly, Highcharts are all popular, but there are a stupid number of javascript libraries out there. If we can just… wrap… those libraries and re-use them in Power BI… that would be HOT. SUPER HOT.
I have a bad feeling I won’t be getting to that in the near future… I’m scheduled out with way too much client work 🙁 So, somebody else take care of it, k?

- The streak is alive! – August 10, 2017
- DAX KEEPFILTERS Plus Bonus Complaining! – July 20, 2017
- VAR: The best thing to happen to DAX since CALCULATE() – July 11, 2017
- Review: Analyzing Data with Power BI and Power Pivot for Excel – June 20, 2017
- Power BI Date Table – June 2, 2017
Scott Senkeresty here… Founder and Owner of Tiny Lizard. Yes, I have done some stuff: A Master’s Degree in Computer Science from California Polytechnic State University in beautiful San Luis Obispo, California. Over twelve years developing software for Microsoft, across Office, Windows and Anti-Malware teams… Read More >>
I don’t think it can be both 6 weeks and 7 weeks since part 1. It is one or the other. In this case, it is 7.14 weeks 🙂
Are you sure it isn’t “matrices”?