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

Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!

Reply
GGimenez
Frequent Visitor

Custom Visualization additional DataViewCategoryColumn

Hello,

 

I'm trying to develop a custom visual that replicates an arc chart for every existing category. I've used the code at https://github.com/kiewic/PowerBI-WaffleChart and I'm on the right path:

However, I'm unable to configure a DataViewCategoryColumn for the second level of categories (The slices of the arc chart). 

 

In the current code, I can set up the first categories: 

 

 

 public static converter(dataView: DataView): PieChartViewModel {
            var labelsArray: Array<string> = [];
            var arcsArray: Array<string> = [];
            var Arcs: DataViewCategoryColumn;
            var category0: DataViewCategoryColumn;
            //matrix.columns.root.children
            if (dataView.categorical.categories && dataView.categorical.categories.length > 0) {
                let categories = dataView.categorical.categories;
                category0 = categories[0];
                
                var rowsCount = category0.values.length;
                labelsArray = [];
                arcsArray = [];
                for (let i = 0; i < rowsCount; i++) {
                    let labelPieces: Array<string> = [];
                    for (let j = 0; j < categories.length; j++) {
                        labelPieces.push(this.formatCategoryValue(categories[j].values[i], categories[j].source.type));
                    }
                    labelsArray.push(labelPieces.join("|"));
                }
                var sliceCount = dataView.categorical.values.grouped();
                //.values["0"].__proto__.source.groupName
                for(let j=0; j<sliceCount.length; j++){
                    console.log(sliceCount[j].values[0]["__proto__"].source.groupName);
                    arcsArray.push(this.formatCategoryValue(sliceCount[j].values[0]["__proto__"].source.groupName, sliceCount[j].values[0]["__proto__"].source.type));
                }
           }

 

 

 

However, I'm unable to find a node from which I could set up a similar object for the second dimension of categories. I could create a new array but I believe I need to use the right object type and I'm struggling to do so.

 

Currently, my dataViewMappings look like this:

   cappabilities.json

 

"dataViewMappings": [
        {
            "conditions": [
                {
                    "Category": {
                        "min": 0,
                        "max": 3
                    },
                    "Paths": {
                        "min": 0,
                        "max": 1
                    },
                    "Values": {
                        "min": 0,
                        "max": 1
                    },
                    "Measure": {
                        "min": 0,
                        "max": 1
                    }
                }
            ],
            "categorical": {
                "categories": {
                    "for": { 
                        "in": "Category"
                    },
                    "dataReductionAlgorithm": { 
                        "top": {}
                    }
                },
                "values": {
                    "group": {
                        "by": "Paths",
                        "select":[
                            {
                               "for":{
                                  "in":"Values"
                               }
                            }
                         ], 
                        "dataReductionAlgorithm": {
                            "top": {}
                        }
                    }
                }
            }
        }

Could you please give me a clue?

Thanks a lot in advance!
Guillermo

 

13 REPLIES 13
GGimenez
Frequent Visitor

bump

v-viig
Community Champion
Community Champion

To get data from the second and third columns of Category you should iterate 

dataView.categorical.categories.map((category, categoryIndex) => {
// TODO: Write your code here
});

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Dear Ignat, 

 

Thanks for your reply. I've tried your code and it works when I add more than one column in the same field holder (Category)..

 

Hoever, I am unable to access the dimension i want to use. I've been able to find it at dataView.categorical.values.grouped() but they lack the right type or idk, but the fact is that when I map it and try to use it in the selectionManager method or I pass it to a valueFormatter, I get a simple array I cannot reference or get the identity object from:

 

var sliceCount = dataView.categorical.values.grouped();   
for(let j=0; j<sliceCount.length; j++){
arcsArray.push(this.formatCategoryValue(sliceCount[j].values[0]["__proto__"].source.groupName, sliceCount[j].values[0]["__proto__"].source.type));
}

 

 

 

Would there be a way to use more than one category? Or may be my dataViewMappings are not correct?

 

Thanks a lot again for your help.

 

G.

 

my full cappabilities file. I'm trying to be able to select by any of the two grouping variables.

{   "dataRoles": [
        {
            "displayName": "Category Data",
            "name": "Category",
            "kind": "Grouping"
        },
        {
            "displayName": "Paths",
            "name": "Paths",
            "kind": "Grouping",
            "description": "The value used to customize the shape of the data points",
            "requiredTypes": [{ "text": true }]
        },
        {
            "displayName": "Values",
            "name": "Values",
            "kind": "Measure",
            "requiredTypes": [{ "numeric": true }, { "integer": true }]
        },
        {
            "displayName": "Measure",
            "name": "measure",
            "kind": "Measure",
            "requiredTypes": [{ "numeric": true }, { "integer": false }]
        },
        {
            "displayName": "Measure Color",
            "name": "measureColor",
            "kind": "Measure",
            "requiredTypes": [{ "numeric": true }, { "integer": false }]
        }
    ],
    "dataViewMappings": [
        {
            "conditions": [
                {
                    "Category": {
                        "min": 0,
                        "max": 3
                    },
                    "Paths": {
                        "min": 0,
                        "max": 1
                    },
                    "Values": {
                        "min": 0,
                        "max": 1
                    },
                    "Measure": {
                        "min": 0,
                        "max": 1
                    }
                }
            ],
            "categorical": {
                "categories": {
                    "for": { 
                        "in": "Paths"
                    },
                    "dataReductionAlgorithm": { 
                        "top": {}
                    }
                },
                "values": {
                    "group": {
                        "by": "Category",
                        "select":[
                            {
                               "for":{
                                  "in":"Values"
                               }
                            }
                         ], 
                        "dataReductionAlgorithm": {
                            "top": {}
                        }
                    }
                }
            }
        },
        {
            "conditions": [
                {
                    "Category": {
                        "min": 0,
                        "max": 3
                    },
                    "Paths": {
                        "min": 0,
                        "max": 1
                    },
                    "Values": {
                        "min": 0,
                        "max": 1
                    },
                    "Measure": {
                        "min": 0,
                        "max": 1
                    }
                }
            ],
            "categorical": {
                "categories": {
                    "for": { 
                        "in": "Category"
                    },
                    "dataReductionAlgorithm": { 
                        "top": {} 
                    }
                },
                "values": {
                    "select": [
                            { "bind": { "to": "measure" } },
                            { "bind": { "to": "measureColor" } }  
                        ]
                    
                }
            }
        }
    ],
    "objects": {
       "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
                    }
                },
                "showHelpLink": {
                    "displayName": "Show Help Button",
                    "type": {
                        "bool": true
                    }
                }
            }
        }
    },
    "supportsHighlight": true,
    "tooltips": {
        "supportedTypes": {
            "default": true,
            "canvas": true
        },
        "roles": [
            "Tooltips"
        ]
    }
}
v-viig
Community Champion
Community Champion

Are you talking about Category? You can add select into categories instead.

 

Please also remove group by statement and use select instead.

 

"select": [{
        "for": {
            "in": "Values"
        }
    },
    {
        "for": {
            "in": "Category"
        }
    }
],

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

hello Ignat,

 

Thanks for your help. I've been following up on your hint and somehow I understand that I may have a design flaw, so I was hoping you could help me review it and define the right approach.

 

I have a series of groups (field Category) for which I want to evaluate the distribution of the total sum of values(field Values) grouped by path (field Paths) for every category. (The pie slices/Arcs)

image.png

 

I need to be able to configure the color of the pie slices so they can be picked through the color Palette. 

 

But I also need to have a 3rd measure (Field Measure) to be shown in the middle of the pie chart, that depends from the field "Category" independently of "Paths" and "Values". It is usually a % hence I cannot aggregate randomly as sometimes will not be a dynamic DAX measure. (I'm OK forcing it to be though)

 

Before I was using unable to configure the color palette for the chart slice groups but everything else was working:

 

{

    "dataRoles": [{
            "displayName": "Category Data",
            "name": "Category",
            "kind": "Grouping"
        },
        {
            "displayName": "Paths",
            "name": "Paths",
            "kind": "Grouping",
            "description": "The value used to customize the shape of the data points",
            "requiredTypes": [{
                "text": true
            }]
        },
        {
            "displayName": "Values",
            "name": "Values",
            "kind": "Measure",
            "requiredTypes": [{
                "numeric": true
            }, {
                "integer": true
            }]
        },
        {
            "displayName": "Measure",
            "name": "measure",
            "kind": "Measure",
            "requiredTypes": [{
                "numeric": true
            }, {
                "integer": false
            }]
        },
        {
            "displayName": "Measure Color",
            "name": "measureColor",
            "kind": "Measure",
            "requiredTypes": [{
                "numeric": true
            }, {
                "integer": false
            }]
        }
    ],
    "dataViewMappings": [{
            "conditions": [{
                "Category": {
                    "min": 0,
                    "max": 3
                },
                "Paths": {
                    "min": 0,
                    "max": 1
                },
                "Values": {
                    "min": 0,
                    "max": 1
                },
                "Measure": {
                    "min": 0,
                    "max": 1
                }
            }],
            "categorical": {
                "categories": {
                    "for": {
                        "in": "Category"
                    },
                    "dataReductionAlgorithm": {
                        "top": {}
                    }
                },
                "values": {
                    "group": {
                        "by": "Paths",
                        "select": [{
                            "bind": {
                                "to": "Values"
                            }
                        }],
                        "dataReductionAlgorithm": {
                            "top": {}
                        }
                    }
                }
            }
        },
        {
            "conditions": [{
                "Category": {
                    "min": 0,
                    "max": 3
                },
                "Paths": {
                    "min": 0,
                    "max": 1
                },
                "Values": {
                    "min": 0,
                    "max": 1
                },
                "Measure": {
                    "min": 0,
                    "max": 1
                }
            }],
            "categorical": {
                "categories": {
                    "for": {
                        "in": "Category"
                    },
                    "dataReductionAlgorithm": {
                        "top": {}
                    }
                },
                "values": {
                    "select": [{
                            "bind": {
                                "to": "measure"
                            }
                        },
                        {
                            "bind": {
                                "to": "measureColor"
                            }
                        }
                    ]

                }
            }
        }
    ],
    "objects": {
        "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
                    }
                },
                "showHelpLink": {
                    "displayName": "Show Help Button",
                    "type": {
                        "bool": true
                    }
                }
            }
        },
        "fontFamily": {
            "displayName": "Font",
            "properties": {
                "MarkerShape": {
                    "displayName": "Marker shape",
                    "type": {
                        "enumeration": [{
                                "displayName": "Default",
                                "description": "helvetica, arial, sans-serif",
                                "value": "helvetica, arial, sans-serif"
                            },
                            {
                                "displayName": "Arial",
                                "value": "Arial"
                            },
                            {
                                "displayName": "Arial Black",
                                "value": "\"Arial Black\""
                            }
                        ]
                    }
                }
            }
        }
    },
    "tooltips": {
        "supportedTypes": {
            "default": true,
            "canvas": true
        },
        "roles": [
            "Tooltips"
        ]
    }
}

Now after raising the question here, I've been working to build something different that I think would allow me to create selectors for the slices, but I cannot see how I can get the measure for the "Category" field.

 

{

    "dataRoles": [{
            "displayName": "Category Data",
            "name": "Category",
            "kind": "Grouping"
        },
        {
            "displayName": "Paths",
            "name": "Paths",
            "kind": "Grouping",
            "description": "The value used to customize the shape of the data points",
            "requiredTypes": [{
                "text": true
            }]
        },
        {
            "displayName": "Values",
            "name": "Values",
            "kind": "Measure",
            "requiredTypes": [{
                "numeric": true
            }, {
                "integer": true
            }]
        },
        {
            "displayName": "Measure",
            "name": "measure",
            "kind": "Measure",
            "requiredTypes": [{
                "numeric": true
            }, {
                "integer": false
            }]
        },
        {
            "displayName": "Measure Color",
            "name": "measureColor",
            "kind": "Measure",
            "requiredTypes": [{
                "numeric": true
            }, {
                "integer": false
            }]
        }
    ],
    "dataViewMappings": [{
            "conditions": [{
                "Category": {
                    "min": 0,
                    "max": 3
                },
                "Paths": {
                    "min": 0,
                    "max": 1
                },
                "Values": {
                    "min": 0,
                    "max": 1
                },
                "Measure": {
                    "min": 0,
                    "max": 1
                }
            }],
            "categorical": {
                "categories": {
                    "for": {
                        "in": "Category"
                    },
                    "dataReductionAlgorithm": {
                        "top": {}
                    }
                },
                "values": {
                        "select": [{ 
                            "for": {
                                "in": "Values"
                            }},{
                            "bind": {
                                "to": "Paths"
                            }},{
                                "bind": {
                                    "to": "measure"
                                }
                            },
                            {
                                "bind": {
                                    "to": "measureColor"
                                }
                            }
                        ],
                        "dataReductionAlgorithm": {
                            "top": {}
                        }
                
                }
            }
        }
    ],
    "objects": {
        "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
                    }
                },
                "showHelpLink": {
                    "displayName": "Show Help Button",
                    "type": {
                        "bool": true
                    }
                }
            }
        },
        "fontFamily": {
            "displayName": "Font",
            "properties": {
                "MarkerShape": {
                    "displayName": "Marker shape",
                    "type": {
                        "enumeration": [{
                                "displayName": "Default",
                                "description": "helvetica, arial, sans-serif",
                                "value": "helvetica, arial, sans-serif"
                            },
                            {
                                "displayName": "Arial",
                                "value": "Arial"
                            },
                            {
                                "displayName": "Arial Black",
                                "value": "\"Arial Black\""
                            }
                        ]
                    }
                }
            }
        }
    },
    "tooltips": {
        "supportedTypes": {
            "default": true,
            "canvas": true
        },
        "roles": [
            "Tooltips"
        ]
    }
}

 

 

Is it possible to group all the independent combinations of category-path in a single colorPalette setting and at the same time have a measure dependent on the category field?

 

Some help will be REALLY appreciated.

 

Thanks a lot in advance,

G.

v-viig
Community Champion
Community Champion

You wanted to specify a color for each segment of each pie. Is that correct?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Yes, that's it.  But the arc segment colors must be the same for all the pies, as they represent the same across pies.

 

 

Now I'm able to edit and store the color picked, but it changes the color for all the other columns of the object:

 

 

 var metadataColumns2: DataViewMetadataColumn[] = this.dataView.metadata.columns.filter(function(d) { 
                if (d.groupName){
                    return true
     }  })

 

 

and in the enumerateObjects function:

 

 case 'stackColorsFormatting':
                
                    for (let barDataPoint of metadataColumns2) {
                        var col =  this.getArcColor(barDataPoint.objects, objectName, "fill", null);
                        objectEnumeration.push({
                            objectName: objectName,
                            displayName: barDataPoint.groupName.toString(),
                            properties: {
                                fill: {
                                    solid: {
                                        color: col.solid.color
                                    }
                                }
                            },
                             
                            selector:  { metadata: barDataPoint.queryName }
                             
                        });
                    }
                    break;

 

And the getArcColor function:

 public getArcColor<T>(objects: DataViewObject, 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;
          }

 

v-viig
Community Champion
Community Champion

Not sure if I understood you well. Have you resolved the issue?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

No, i'm still stuck. 

Here is how it looks now:

https://gist.github.com/sineline/f4f4074919777079d59cbf7551bc1d47

 

 

v-viig
Community Champion
Community Champion

You should use group-by Category to group values. In such case you will be able to generate a proper SelectionId.

 

"values": {
    "group": {
        "by": "Paths",
        "select":[

Please have a look at this example.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

I believe this is how I've got it right now, with the group by (See gist in previous post).

With it I get the right values, but I want to enumerate and set colors per group (Which are the pie slices).

 

Can I build the selectors the same way when enumerating the different series? (For the pie slices coloring)

 

For the moment, I've been playing with this function.. but i dont know if I'm in the right path:

 

 

case "stackColorsFormatting":
 	var metadataColumns2: DataViewMetadataColumn[] = this.dataView.metadata.columns.filter( function(d) { if (d.groupName) { return true; } } );
	for (let barDataPoint of metadataColumns2) {
	 console.log("create selection id?");
	 objectEnumeration.push({
	   objectName: objectName,
	   displayName:   barDataPoint.groupName.toString(),
	   properties: {
		 fill:this.getArcColor<object>(barDataPoint.objects,objectName,"fill",null)
	   },
	   selector: { id: this.host.createSelectionIdBuilder().withSeries( this.dataView.categorical.values,this.dataView.categorical.values[0] ).createSelectionId().getKey() }
	   
	 });
   }
   break;

 

v-viig
Community Champion
Community Champion

@GGimenez Could you please share source code to make some changes?

 

You can send code to pbicvsupport@microsoft.com.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Helpful resources

Announcements
April AMA free

Microsoft Fabric AMA Livestream

Join us Tuesday, April 09, 9:00 – 10:00 AM PST for a live, expert-led Q&A session on all things Microsoft Fabric!

March Fabric Community Update

Fabric Community Update - March 2024

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