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

custom visual enumeration issues

I'm developing a custom visual for PowerBI. I have a question . After investigating and the documentation is not very detailed I can't insert items in the dropbox of the capabilities objects, ie I want to have the columns of my table dynamically in a property object like the matrix table has.How to do this?

 

zzzzz.jpg_ei.jpgissue.jpg

1 ACCEPTED SOLUTION

Are you tring to add a dynamic property for each column that has been added to a custom visual? If so, then I will describe what I am using to acheive that result where you add your property values into the objects collection for a specific column using the DataViewMetadataColumn. Here is an example of a demo custom visual named snazzyTable which produces a custom table where I have added three columns. As you can see, this custom visual gives the user the ability to configure bold formatting on each column seperately.

 

Bold formatting can be enabled/disabled on each column seperatelyBold formatting can be enabled/disabled on each column seperately

It took me a little time to figure out working with dynamic objects but the key is recognizing that many objects in the Power BI visuals API have their own objects collections to track custom properties. For example, the metadata for the column named Sales Revenue is persisted into the following path.

 

CustomColumnPropertyMetadata.png

 

Here is how to recreate this effect. Begin in the capabilities.json file by defining a property just like you would for a single static property.

 

 

"objects": {
    "columnFormatting": {
      "displayName": "Bold Column Formatting",
      "properties": {
        "fontBold": {
          "displayName": "Font Bold",
          "type": { "bool": true }
        }
      }
    }
  }

Next, define a generic method to retreive metadata property values. Here is my generic implementation of getValue.

 

 

 

public getValue<T>(objects: DataViewObjects, objectName: string, propertyName: string, defaultValue: T): T {
  if (objects) {
    let object = objects[objectName];
    if (object) {
      let property: T = <T>object[propertyName];
      if (property !== undefined) {
        return property;
      }
    }
  }
  return defaultValue;
}

 

Now comes the tricky part. When you implement enumerateObjectInstance, you must use a special selector for column metadata which invovles creating selector object with metadata propert to reference the specific column.

 

selector: { metadata: "YourColumnQueryNameHere" }

Here is the full implementation of enumerateObjectInstance. In particualr, check to see how it loops through each metadata column and adds a new property with a selector that includes the column query name.

 

public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
  let objectName = options.objectName;
  let objectEnumeration: VisualObjectInstance[] = [];

  var metadataColumns: DataViewMetadataColumn[] = this.dataView.metadata.columns;

  switch (objectName) {
    case 'columnFormatting':
      for (var i = 0; i < metadataColumns.length; i++) {
        var currentColumn: DataViewMetadataColumn = metadataColumns[i];
        objectEnumeration.push({
          objectName: objectName,
          displayName: currentColumn.displayName,
          properties: {
            fontBold: this.getValue<boolean>(currentColumn.objects, objectName, "fontBold", false)
          },
          selector: { metadata: currentColumn.queryName }
        });

      };
      break;
  }
  return objectEnumeration;
}

That is all it takes to display the properties in the Format pane and to make these properties editable to the user designig a report. The last part is actually doing something difference once the user sets a column property value I handle this in the update method by querying the column property value and using the result to determine when to make the cell bold or not.

 

if (this.getValue<boolean>(columns[columnIndex].objects, "columnFormatting", "fontBold", false)) {
  tableCell.css({ "font-weight": "bold" });
}

Here's a link to the source code for snazzyTable in a GitHub repository.

 

https://github.com/CriticalPathTraining/CustomVisualsForPowerBI/tree/master/snazzyTable

 

View solution in original post

7 REPLIES 7
Community Support
Community Support

@joao_pires,

 

Based on my research, you may use dataViews in VisualUpdateOptions to make it.

Community Support Team _ Sam Zha
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Hi @v-chuncz-msft ,

 

yes, i have data of columns of dataViews in VisualUpdateOptions, but how make a combo dinamic with this values?

 

regards 

 

joão

Are you tring to add a dynamic property for each column that has been added to a custom visual? If so, then I will describe what I am using to acheive that result where you add your property values into the objects collection for a specific column using the DataViewMetadataColumn. Here is an example of a demo custom visual named snazzyTable which produces a custom table where I have added three columns. As you can see, this custom visual gives the user the ability to configure bold formatting on each column seperately.

 

Bold formatting can be enabled/disabled on each column seperatelyBold formatting can be enabled/disabled on each column seperately

It took me a little time to figure out working with dynamic objects but the key is recognizing that many objects in the Power BI visuals API have their own objects collections to track custom properties. For example, the metadata for the column named Sales Revenue is persisted into the following path.

 

CustomColumnPropertyMetadata.png

 

Here is how to recreate this effect. Begin in the capabilities.json file by defining a property just like you would for a single static property.

 

 

"objects": {
    "columnFormatting": {
      "displayName": "Bold Column Formatting",
      "properties": {
        "fontBold": {
          "displayName": "Font Bold",
          "type": { "bool": true }
        }
      }
    }
  }

Next, define a generic method to retreive metadata property values. Here is my generic implementation of getValue.

 

 

 

public getValue<T>(objects: DataViewObjects, objectName: string, propertyName: string, defaultValue: T): T {
  if (objects) {
    let object = objects[objectName];
    if (object) {
      let property: T = <T>object[propertyName];
      if (property !== undefined) {
        return property;
      }
    }
  }
  return defaultValue;
}

 

Now comes the tricky part. When you implement enumerateObjectInstance, you must use a special selector for column metadata which invovles creating selector object with metadata propert to reference the specific column.

 

selector: { metadata: "YourColumnQueryNameHere" }

Here is the full implementation of enumerateObjectInstance. In particualr, check to see how it loops through each metadata column and adds a new property with a selector that includes the column query name.

 

public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
  let objectName = options.objectName;
  let objectEnumeration: VisualObjectInstance[] = [];

  var metadataColumns: DataViewMetadataColumn[] = this.dataView.metadata.columns;

  switch (objectName) {
    case 'columnFormatting':
      for (var i = 0; i < metadataColumns.length; i++) {
        var currentColumn: DataViewMetadataColumn = metadataColumns[i];
        objectEnumeration.push({
          objectName: objectName,
          displayName: currentColumn.displayName,
          properties: {
            fontBold: this.getValue<boolean>(currentColumn.objects, objectName, "fontBold", false)
          },
          selector: { metadata: currentColumn.queryName }
        });

      };
      break;
  }
  return objectEnumeration;
}

That is all it takes to display the properties in the Format pane and to make these properties editable to the user designig a report. The last part is actually doing something difference once the user sets a column property value I handle this in the update method by querying the column property value and using the result to determine when to make the cell bold or not.

 

if (this.getValue<boolean>(columns[columnIndex].objects, "columnFormatting", "fontBold", false)) {
  tableCell.css({ "font-weight": "bold" });
}

Here's a link to the source code for snazzyTable in a GitHub repository.

 

https://github.com/CriticalPathTraining/CustomVisualsForPowerBI/tree/master/snazzyTable

 

View solution in original post

Hi @TedPattison,

 

Thank you for the long post, but it was very useful, the trick was in the 

 

selector: { metadata: "YourColumnQueryNameHere" }

and

displayName: currentColumn.displayName,

 

thanks you so much 

 

regards 

 

João

Anonymous
Not applicable

hi @joao_pires , and how you add dynamic data to combo box?

 

i try all step above and my combo box still show the static data from capabily file

 

this is my visual.ts

visual.ts.01.PNG

 

and this is my browser console loglog.ts.01.PNG

hi @Anonymous ,

 

when dev my custom visual this option is not possible.

I make a combobox dinamic into CV in CSS.

 

hope is help you.

Anonymous
Not applicable

thanks @joao_pires  and @TedPattison 

 

finally I'm create dynamic color picker as much as fields values selected, and strore in dataview using selector metadata.

Helpful resources

Announcements
secondImage

Congratulations!

We are excited to announce the Power BI Super Users!

Wave Release 2

Check out the updates in Power BI.

Overview of Power BI 2020 release wave 2!

Get Ready for Power BI Dev Camp

Get Ready for Power BI Dev Camp

Mark your calendars and join us for our next Power BI Dev Camp!.

secondImage

The largest Power BI virtual conference

100+ sessions, 100+ speakers, Product managers, MVPs, and experts. All about Power BI. Attend online or watch the recordings.

Top Solution Authors
Top Kudoed Authors