Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Get certified in Microsoft Fabric—for free! For a limited time, the Microsoft Fabric Community team will be offering free DP-600 exam vouchers. Prepare now

Reply
joao_pires
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

9 REPLIES 9
v-chuncz-msft
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

 

I'd like to see this answer updated to use the new getFormattingModel API instead of enumerateObjectInstance

Your reply is a lifesaver, I was looking for this! I will write a blog article out of this as a continuation of series on how to develop custom visuals, I will make sure to give you credit!

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
OCT PBI Update Carousel

Power BI Monthly Update - October 2024

Check out the October 2024 Power BI update to learn about new features.

September Hackathon Carousel

Microsoft Fabric & AI Learning Hackathon

Learn from experts, get hands-on experience, and win awesome prizes.

October NL Carousel

Fabric Community Update - October 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors