Forum Discussion
How do I find out what doesn't work?
- 9 years ago
You should use module instead of namespace:
namespace powerbi.extensibility.visual
As a result you should have this:
module powerbi.extensibility.visual
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
Make sure you run command in the right visual project and the file name in tsconfig.json is correct. To debug your visual, use the try...catch statement.
https://github.com/Microsoft/PowerBI-visuals/blob/master/tools/debugging.md
- ConnectedRoman9 years agoFrequent Visitor
Hello, thank you for your time.
I have already tried debugging, but there were no errors. When I try compiling my code with pbiviz start, it throws this error in the .tmp/precompile/visualPlugin.ts file:
{Projectname} is not a property of "Visual"
The filenames/-paths in pbiviz.json and tsconfig.json are right.
- v-viig9 years agoCommunity Champion
Did you fill capabilities.json?
Could you please share your current code?
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- ConnectedRoman9 years agoFrequent Visitor
Yes, of course.
tsconfig.json:
{ "compilerOptions": { "allowJs": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "ES5", "sourceMap": true, "out": "./.tmp/build/barChart.js" }, "files": [ "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.d.ts", "node_modules/powerbi-visuals-utils-typeutils/lib/index.d.ts", "node_modules/powerbi-visuals-utils-colorutils/lib/index.d.ts", ".api/v1.7.0/PowerBI-visuals.d.ts", "src/barChart.ts", "src/objectEnumerationUtility.ts", "src/colorPalette.ts" ] }pbiviz.json:
{ "visual": { "name": "secondTry", "displayName": "secondTry", "guid": "secondTry907B5A8A17DF4B48A41E2DB3737B35D8", "visualClassName": "secondTry.ts", "version": "1.0.0", "description": "", "supportUrl": "", "gitHubUrl": "" }, "apiVersion": "1.7.0", "author": { "name": "", "email": "" }, "assets": { "icon": "assets/icon.png" }, "externalJS": [ "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js", "node_modules/powerbi-visuals-utils-typeutils/lib/index.js", "node_modules/powerbi-visuals-utils-colorutils/lib/index.js", "node_modules/d3/d3.min.js" ], "style": "style/visual.less", "capabilities": "capabilities.json", "dependencies": "dependencies.json", "stringResources": [] }capabilities.json:
{ "dataRoles": [ { "displayName": "Category Data", "name": "category", "kind": "Grouping" }, { "displayName": "Measure Data", "name": "measure", "kind": "Measure" } ], "dataViewMappings": [ { "conditions": [ { "category": { "max": 1 }, "measure": { "max": 1 } } ], "categorical": { "categories": { "for": { "in": "category" } }, "values": { "select": [ { "bind": { "to": "measure" } } ] } } } ], "objects": { "enableAxis": { "displayName": "Enable Axis", "properties": { "show": { "displayName": "Enable Axis", "type": { "bool": true } } } }, "colorSelector": { "displayName": "Data Colors", "properties": { "fill": { "displayName": "Color", "type": { "fill": { "solid": { "color": true } } } } } }, "generalView": { "displayName": "General View", "properties": { "opacity": { "displayName": "Bars Opacity", "type": { "integer": true } } } } } }barChart.ts:
namespace powerbi.extensibility.visual { /** * Interface for barcharts viewmodel. * * @interface * @property {barChartDataPoint[]} dataPoints - Set of datapoints * @property {number} dataMax - Highest data value in dataPoints * @property {BarChartSettings} settings - Viewmodel settings (?) */ interface BarChartViewModel { dataPoints: BarChartDataPoint[]; dataMax: number; settings: BarChartSettings; } /** * A datapoint. * * @interface * @property {PrimitiveValue} value - Value for datapoint * @property {string} category - Categorization of datapoint * @property {string} color - Color of datapoint * @property {ISelectionId} selectionId - Id of the datapoint when selected. */ interface BarChartDataPoint { value: PrimitiveValue; category: string; color: string; selectionId: ISelectionId; } /** * Settings of barchart * * @interface * @property {object} enableAxis - Has property "show" -> boolean * @property {object} generalView - Has property "opacity" -> number */ interface BarChartSettings { enableAxis: { show: boolean; }; generalView: { opacity: number; }; } /** * Function that converts queried data into a view model that will be used by the visual. * * @function * @param {VisualUpdateOptions} options - Contains references to the size of the container * and the dataView which contains all the data * the visual had queried. * @param {IVisualHost} host - Contains references to the host which contains services */ function visualTransform( options: VisualUpdateOptions, host: IVisualHost ): BarChartViewModel { //Getting colors let Colors = null; //changed for sharing //DataView object that contains all data needed to render visual (capabilities) let dataViews = options.dataViews; //Saving default settings in var let defaultSettings: BarChartSettings = { enableAxis: { show: false }, generalView: { opacity: 100 } }; //Creating viewmodel let viewModel: BarChartViewModel = { dataPoints: [], dataMax: 0, settings: <BarChartSettings>{} }; //Returning viewmodel if it's not empty if ( !dataViews || !dataViews[0] || !dataViews[0].categorical || !dataViews[0].categorical.categories || !dataViews[0].categorical.categories[0].source || !dataViews[0].categorical.values ) return viewModel; //Saving JSON object in vars let categorical = dataViews[0].categorical; let category = categorical.categories[0]; let dataValue = categorical.values[0]; let barChartDataPoints: BarChartDataPoint[] = []; let dataMax: number; let colorPalette: IColorPalette = host.colorPalette; //Change to colors ? let objects = dataViews[0].metadata.objects; let barChartSettings: BarChartSettings = { //setting settings enableAxis: { show: getValue<boolean>( //method in objectEnumerationUtility.ts objects, "enableAxis", "show", defaultSettings.enableAxis.show ) }, generalView: { opacity: getValue<number>( //method in objectEnumerationUtility.ts objects, "generalView", "opacity", defaultSettings.generalView.opacity ) } }; for ( //Going through each datapoint var i = 0, len = Math.max(category.values.length, dataValue.values.length); i < len; i++ ) { let defaultColor: Fill = { //defining defaultColor of datapoint solid: { color: colorPalette.getColor(Colors[i] + "").value } }; //Colors[i] + "").value barChartDataPoints.push({ //Pushing datapoints into array category: category.values[i] + "", value: dataValue.values[i], color: getCategoricalObjectValue<Fill>( category, i, "colorSelector", "fill", defaultColor ).solid.color, selectionId: host .createSelectionIdBuilder() .withCategory(category, i) .createSelectionId() }); } //Saving max value in var dataMax = <number>dataValue.maxLocal; //Returning newly constructed VisualData return { dataPoints: barChartDataPoints, dataMax: dataMax, settings: barChartSettings }; } /** * The barChart class. * * @class */ export class secondTry implements IVisual { private svg: d3.Selection<SVGElement>; private host: IVisualHost; private selectionManager: ISelectionManager; private xAxis: d3.Selection<SVGElement>; private barContainer: d3.Selection<SVGElement>; private barChartSettings: BarChartSettings; private barChartContainer: d3.Selection<SVGElement>; private barDataPoints: BarChartDataPoint[]; static Config = { xScalePadding: 0.1, solidOpacity: 1, transparentOpacity: 0.5, margins: { top: 0, right: 0, bottom: 25, left: 30 }, xAxisFontMultiplier: 0.04 }; /** * Creates barChart-instance. * @param options Reference to element that will contain the visual. */ constructor(options: VisualConstructorOptions) { //Setting a host: Contains various services for visual (color, createSelectionIdBuilder/Manager, allowInteraction) this.host = options.host; //Creates a selection manager: Notifies if something was selected this.selectionManager = options.host.createSelectionManager(); //Creates "svg" element on site and saves it in var let svg = (this.svg = d3 .select(options.element) .append("svg") .classed("barChart", true)); //Creates "g" element and classes it barContainer/xAxis, saves it in var this.barContainer = svg.append("g").classed("barContainer", true); this.xAxis = svg.append("g").classed("xAxis", true); } /** * Updates state of visual when changed. * @param options Reference to datapoints/container. */ @logExceptions() public update(options: VisualUpdateOptions) { //getting the viewModel with visualTransform -> Creates valid datapoints for visual let viewModel: BarChartViewModel = visualTransform(options, this.host); let settings = (this.barChartSettings = viewModel.settings); this.barDataPoints = viewModel.dataPoints; //getting viewport sizes let width = options.viewport.width; let height = options.viewport.height; //setting correct sizes to visual this.svg.attr({ width: width, height: height }); //if enableAxis.show == true if (settings.enableAxis.show) { let margins = secondTry.Config.margins; height -= margins.bottom; //Höhe um untere Margin verkleinern } //Correcting font-size this.xAxis.style( "font-size", d3.min([height, width]) * secondTry.Config.xAxisFontMultiplier ); //Correcting y-scale let yScale = d3.scale .linear() .domain([0, viewModel.dataMax]) .range([height, 0]); //correcting x-scale let xScale = d3.scale .ordinal() .domain(viewModel.dataPoints.map(d => d.category)) .rangeRoundBands([0, width], secondTry.Config.xScalePadding, 0.2); //Creating xAxis? let xAxis = d3.svg.axis().scale(xScale).orient("bottom"); //Moving x-Axis down by {height} pixels this.xAxis.attr("transform", "translate(0, " + height + ")").call(xAxis); //Selecting all .bar elements into barContainer and saving in var let bars = this.barContainer.selectAll(".bar").data(viewModel.dataPoints); //Placeholder nodes bars.enter().append("rect").classed("bar", true); bars.attr({ width: xScale.rangeBand(), height: d => height - yScale(<number>d.value), y: d => yScale(<number>d.value), x: d => xScale(d.category), fill: d => d.color, //Fat Arrow means function. "function d returns d.color". Doesn't have own "this" "fill-opacity": viewModel.settings.generalView.opacity / 100 }); let selectionManager = this.selectionManager; let allowInteractions = this.host.allowInteractions; //Must be anonymous function isntead of =>, d3 uses 'this' as ref to clicked obj bars.on("click", function(d) { // Allow selection only if the visual is rendered in a view that supports interactivity (e.g. Report) if (allowInteractions) { selectionManager.select(d.selectionId).then((ids: ISelectionId[]) => { bars.attr({ "fill-opacity": ids.length > 0 //If length of id is > 0, then transparent, else solid ? secondTry.Config.transparentOpacity : secondTry.Config.solidOpacity }); //Setting clicked obj solid d3.select(this).attr({ "fill-opacity": secondTry.Config.solidOpacity }); }); (<Event>d3.event).stopPropagation(); } }); //Remove elements with no data bars.exit().remove(); } /** * Enumerates through the objects defined in the capabilities and adds the properties to the format pane * * @function * @param {EnumerateVisualObjectInstancesOptions} options - Map of defined objects */ @logExceptions() public enumerateObjectInstances( options: EnumerateVisualObjectInstancesOptions ): VisualObjectInstanceEnumeration { let objectName = options.objectName; let objectEnumeration: VisualObjectInstance[] = []; switch (objectName) { case "enableAxis": objectEnumeration.push({ objectName: objectName, properties: { show: this.barChartSettings.enableAxis.show }, selector: null }); break; case "colorSelector": for (let barDataPoint of this.barDataPoints) { objectEnumeration.push({ objectName: objectName, displayName: barDataPoint.category, properties: { fill: { solid: { color: barDataPoint.color } } }, selector: barDataPoint.selectionId }); } break; case "generalView": objectEnumeration.push({ objectName: objectName, properties: { opacity: this.barChartSettings.generalView.opacity }, validValues: { opacity: { numberRange: { min: 10, max: 100 } } }, selector: null }); break; } return objectEnumeration; } } /** * Logging exceptions for debugging purposes. * @function */ export function logExceptions(): MethodDecorator { return function( target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<Function> ): TypedPropertyDescriptor<Function> { return { value: function() { try { return descriptor.value.apply(this, arguments); } catch (e) { console.error(e); throw e; } } }; }; } }.tmp/precompile/visualPlugin.ts:
module powerbi.visuals.plugins { export var secondTry907B5A8A17DF4B48A41E2DB3737B35D8_DEBUG = { name: 'secondTry907B5A8A17DF4B48A41E2DB3737B35D8_DEBUG', displayName: 'secondTry', class: 'secondTry.ts', version: '1.0.0', apiVersion: '1.7.0', create: (options: extensibility.visual.VisualConstructorOptions) => new powerbi.extensibility.visual.secondTry907B5A8A17DF4B48A41E2DB3737B35D8.secondTry.ts(options), custom: true }; }