Προσθήκη υποστήριξης διερεύνησηςAdd Drill-Down support
Οι απεικονίσεις Power BI μπορούν να χρησιμοποιήσουν την άντληση του Power BI.Power BI visuals can use Power BI's drill-down.
Διαβάστε περισσότερα σχετικά με τη διερεύνηση του Power BI εδώRead more about Power BI drill-down here
Ενεργοποίηση της υποστήριξης διερεύνησης στην απεικόνισηEnable drill-down support in the visual
Για υποστήριξη διερεύνησης στην απεικόνισή σας, προσθέστε ένα νέο πεδίο στη διερεύνηση με ονομασία capabilities.json
, που διαθέτει μία ιδιότητα:To support drill down in your visual, add a new field to capabilities.json
named "drill-down", which has one property:
*roles - the name of the dataRole you want to enable drill-down on.
Σημείωση
Το dataRole διερεύνησης πρέπει να είναι τύπου Grouping
.The drill-down dataRole must be of Grouping
type.
Η ιδιότητα max
στις προϋποθέσεις dataRole πρέπει να οριστεί σε 1.max
property in the dataRole conditions must be set to 1.
Όταν προσθέσετε τον ρόλο στη διερεύνηση, οι χρήστες μπορούν να μεταφέρουν πολλαπλά πεδία στον ρόλο δεδομένων.Once you add the role to drill-down, users can drag multiple fields into the data role.
παράδειγμα:example:
{
"dataRoles": [
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"drilldown": {
"roles": [
"category"
]
},
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"select": [
{
"bind": {
"to": "value"
}
}
]
}
}
}
]
}
Δημιουργία της απεικόνισης με υποστήριξη διερεύνησηςCreate the visual with drill-down support
ΕκτέλεσηRun
pbiviz new testDrillDown -t default
για τη δημιουργία ενός προεπιλεγμένου δείγματος απεικόνισης.to create a default sample visual. Και εφαρμόστε το παραπάνω δείγμα capabilities.json
στην απεικόνιση που δημιουργήθηκε μόλις.And apply the above sample of capabilities.json
to the newly created visual.
Δημιουργήστε την ιδιότητα για το κοντέινερ div
προκειμένου να διατηρεί στοιχεία HTML της απεικόνισης:Create the property for div
container to hold HTML elements of the visual:
"use strict";
import "core-js/stable";
import "./../style/visual.less";
// imports
export class Visual implements IVisual {
// visual properties
// ...
private div: HTMLDivElement; // <== NEW PROPERTY
constructor(options: VisualConstructorOptions) {
// constructor body
// ...
}
public update(options: VisualUpdateOptions) {
// update method body
// ...
}
private static parseSettings(dataView: DataView): VisualSettings {
return <VisualSettings>VisualSettings.parse(dataView);
}
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
}
}
Ενημερώστε την κατασκευή της απεικόνισης:Update the constructor of the visual:
export class Visual implements IVisual {
// visual properties
// ...
private div: HTMLDivElement;
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.target = options.element;
this.updateCount = 0;
const new_p: HTMLElement = document.createElement("p");
new_p.appendChild(document.createTextNode("Hierarchy level:"));
const new_em: HTMLElement = document.createElement("em");
this.textNode = document.createTextNode(this.updateCount.toString());
new_em.appendChild(this.textNode);
new_p.appendChild(new_em);
this.target.appendChild(new_p);
this.div = document.createElement("div"); // <== CREATE DIV ELEMENT
this.target.appendChild(this.div);
}
}
Ενημερώστε τη μέθοδο update
της απεικόνισης για να δημιουργήσετε button
s:Update the update
method of the visual to create button
s:
export class Visual implements IVisual {
// ...
public update(options: VisualUpdateOptions) {
this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
console.log('Visual update', options);
const dataView: DataView = options.dataViews[0];
const categoricalDataView: DataViewCategorical = dataView.categorical;
// don't create elements if no data
if (!options.dataViews[0].categorical ||
!options.dataViews[0].categorical.categories) {
return
}
// to display current level of hierarchy
if (typeof this.textNode !== undefined) {
this.textNode.textContent = categoricalDataView.categories[categoricalDataView.categories.length - 1].source.displayName.toString();
}
// remove old elements
// for better performance use D3js pattern:
// https://d3js.org/#enter-exit
while (this.div.firstChild) {
this.div.removeChild(this.div.firstChild);
}
// create buttons for each category value
categoricalDataView.categories[categoricalDataView.categories.length - 1].values.forEach( (category: powerbi.PrimitiveValue, index: number) => {
let button = document.createElement("button");
button.innerText = category.toString();
this.div.appendChild(button);
})
}
// ...
Εφαρμόστε απλά στυλ στο .\style\visual.less
:Apply simple styles in .\style\visual.less
:
button {
margin: 5px;
min-width: 50px;
min-height: 50px;
}
Προετοιμάστε το δείγμα δεδομένων για έλεγχο της απεικόνισης:Prepare sample data to test the visual:
H1H1 | H2H2 | H3H3 | VALUESVALUES |
---|---|---|---|
AA | A1A1 | A11A11 | 11 |
AA | A1A1 | A12A12 | 22 |
AA | A2A2 | A21A21 | 33 |
AA | A2A2 | A22A22 | 44 |
AA | A3A3 | A31A31 | 55 |
AA | A3A3 | A32A32 | 66 |
BB | B1B1 | B11B11 | 77 |
BB | B1B1 | B12B12 | 88 |
BB | B2B2 | B21B21 | 99 |
BB | B2B2 | B22B22 | 1010 |
BB | B3B3 | B31B31 | 1111 |
BB | B3B3 | B32B32 | 1212 |
Και δημιουργήστε Ιεραρχία στο Power BI Desktop:And create Hierarchy in Power BI Desktop:
Συμπεριλάβετε όλες τις στήλες κατηγοριών (H1, H2, H3) στη νέα ιεραρχία:Include all category columns (H1, H2, H3) to the new hierarchy:
Ύστερα από αυτά τα βήματα θα πρέπει να λάβετε την ακόλουθη απεικόνιση:After those steps you should get following visual:
Προσθήκη μενού περιβάλλοντος στα οπτικά στοιχείαAdd context menu to visual elements
Σε αυτό το βήμα θα προσθέσετε μενού περιβάλλοντος στο κουμπί στην απεικόνιση:In this step you'll add context menu to the button's on the visual:
Για να δημιουργήσετε μενού περιβάλλοντος, αποθηκεύστε το αντικείμενο host
στις ιδιότητες της απεικόνισης και καλέστε τη μέθοδο createSelectionManager
στη διαχείριση δημιουργίας επιλογών για να εμφανίσετε ένα μενού περιβάλλοντος χρησιμοποιώντας το API Απεικονίσεις Power BI.To create context menu, save host
object in the properties of the visual and call createSelectionManager
method to the create selection manager to display a context menu by using Power BI Visuals API.
"use strict";
import "core-js/stable";
import "./../style/visual.less";
// imports
import powerbiVisualsApi from "powerbi-visuals-api";
import ISelectionManager = powerbiVisualsApi.extensibility.ISelectionManager;
import ISelectionId = powerbiVisualsApi.visuals.ISelectionId;
import ISelectionIdBuilder = powerbiVisualsApi.visuals.ISelectionIdBuilder;
export class Visual implements IVisual {
// visual properties
// ...
private div: HTMLDivElement;
private host: IVisualHost; // <== NEW PROPERTY
private selectionManager: ISelectionManager; // <== NEW PROPERTY
constructor(options: VisualConstructorOptions) {
// constructor body
// save the host in the visuals properties
this.host = options.host;
// create selection manager
this.selectionManager = this.host.createSelectionManager();
// ...
}
public update(options: VisualUpdateOptions) {
// update method body
// ...
}
// ...
}
Αλλάξτε το σώμα της επιστροφής κλήσης συνάρτησης forEach
σε:Change the body of forEach
function callback to:
categoricalDataView.categories[categoricalDataView.categories.length - 1].values.forEach( (category: powerbi.PrimitiveValue, index: number) => {
// create selectionID for each category value
let selectionID: ISelectionID = this.host.createSelectionIdBuilder()
.withCategory(categoricalDataView.categories[0], index)
.createSelectionId();
let button = document.createElement("button");
button.innerText = category.toString();
// add event listener to click event
button.addEventListener("click", (event) => {
// call select method in the selection manager
this.selectionManager.select(selectionID);
});
button.addEventListener("contextmenu", (event) => {
// call showContextMenu method to display context menu on the visual
this.selectionManager.showContextMenu(selectionID, {
x: event.clientX,
y: event.clientY
});
event.preventDefault();
});
this.div.appendChild(button);
});
Εφαρμογή δεδομένων στην απεικόνιση:Apply data to the visual:
Στο τελικό βήμα θα πρέπει να λάβετε απεικόνιση με επιλογές και μενού περιβάλλοντος:In the final step you should get visual with selections and context menu:
Προσθήκη υποστήριξης διερεύνησης για αντιστοίχιση προβολής δεδομένων μήτραςAdd drill-down support for matrix data view mapping
Προετοιμάστε δείγμα δεδομένων για έλεγχο της απεικόνισης με αντιστοιχίσεις προβολής δεδομένων μήτρας:Prepare sample data to test the visual with matrix data view mappings:
Σειρά1Row1 | Σειρά2Row2 | Σειρά3Row3 | Στήλη1Column1 | Στήλη2Column2 | Column3Column3 | ΤιμέςValues |
---|---|---|---|---|---|---|
R1R1 | R11R11 | R111R111 | C1C1 | C11C11 | C111C111 | 11 |
R1R1 | R11R11 | R112R112 | C1C1 | C11C11 | C112C112 | 22 |
R1R1 | R11R11 | R113R113 | C1C1 | C11C11 | C113C113 | 33 |
R1R1 | R12R12 | R121R121 | C1C1 | C12C12 | C121C121 | 44 |
R1R1 | R12R12 | R122R122 | C1C1 | C12C12 | C122C122 | 55 |
R1R1 | R12R12 | R123R123 | C1C1 | C12C12 | C123C123 | 66 |
R1R1 | R13R13 | R131R131 | C1C1 | C13C13 | C131C131 | 77 |
R1R1 | R13R13 | R132R132 | C1C1 | C13C13 | C132C132 | 88 |
R1R1 | R13R13 | R133R133 | C1C1 | C13C13 | C133C133 | 99 |
R2R2 | R21R21 | R211R211 | C2C2 | C21C21 | C211C211 | 1010 |
R2R2 | R21R21 | R212R212 | C2C2 | C21C21 | C212C212 | 1111 |
R2R2 | R21R21 | R213R213 | C2C2 | C21C21 | C213C213 | 1212 |
R2R2 | R22R22 | R221R221 | C2C2 | C22C22 | C221C221 | 1313 |
R2R2 | R22R22 | R222R222 | C2C2 | C22C22 | C222C222 | 1414 |
R2R2 | R22R22 | R223R223 | C2C2 | C22C22 | C223C223 | 1616 |
R2R2 | R23R23 | R231R231 | C2C2 | C23C23 | C231C231 | 1717 |
R2R2 | R23R23 | R232R232 | C2C2 | C23C23 | C232C232 | 1818 |
R2R2 | R23R23 | R233R233 | C2C2 | C23C23 | C233C233 | 1919 |
Εφαρμόστε την παρακάτω αντιστοίχιση προβολής δεδομένων για την απεικόνιση:Apply following dataview mapping for the visual:
{
"dataRoles": [
{
"displayName": "Columns",
"name": "columns",
"kind": "Grouping"
},
{
"displayName": "Rows",
"name": "rows",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"drilldown": {
"roles": [
"columns",
"rows"
]
},
"dataViewMappings": [
{
"matrix": {
"columns": {
"for": {
"in": "columns"
}
},
"rows": {
"for": {
"in": "rows"
}
},
"values": {
"for": {
"in": "value"
}
}
}
}
]
}
Εφαρμογή δεδομένων στην απεικόνιση:Apply data to the visual:
Εισαγάγετε τις απαραίτητες διασυνδέσεις για επεξεργασία των αντιστοιχίσεων προβολής δεδομένων μήτρας:Import required interfaces to process matrix data view mappings:
// ...
import DataViewMatrix = powerbi.DataViewMatrix;
import DataViewMatrixNode = powerbi.DataViewMatrixNode;
import DataViewHierarchyLevel = powerbi.DataViewHierarchyLevel;
// ...
Δημιουργήστε δύο ιδιότητες για δύο div
στοιχείων γραμμών και στηλών:Create two properties for two div
s of rows and columns elements:
export class Visual implements IVisual {
// ...
private rowsDiv: HTMLDivElement;
private colsDiv: HTMLDivElement;
// ...
constructor(options: VisualConstructorOptions) {
// constructor body
// ...
// Create div elements and append to main div of the visual
this.rowsDiv = document.createElement("div");
this.target.appendChild(this.rowsDiv);
this.colsDiv = document.createElement("div");
this.target.appendChild(this.colsDiv);
}
// ...
}
Ελέγξτε τα δεδομένα πριν την απόδοση στοιχείων και προβάλετε το τρέχον επίπεδο ιεραρχίας:Check the data before rendering elements and display the current level of hierarchy:
export class Visual implements IVisual {
// ...
constructor(options: VisualConstructorOptions) {
// constructor body
}
public update(options: VisualUpdateOptions) {
this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
console.log('Visual update', options);
const dataView: DataView = options.dataViews[0];
const matrixDataView: DataViewMatrix = dataView.matrix;
// if the visual doesn't receive the data no reason to continue rendering
if (!matrixDataView ||
!matrixDataView.columns ||
!matrixDataView.rows ) {
return
}
// to display current level of hierarchy
if (typeof this.textNode !== undefined) {
this.textNode.textContent = categoricalDataView.categories[categoricalDataView.categories.length - 1].source.displayName.toString();
}
// ...
}
// ...
}
Δημιουργήστε τη συνάρτηση treeWalker
για να διατρέξετε την ιεραρχία:Create function treeWalker
for traverse the hierarchy:
export class Visual implements IVisual {
// ...
public update(options: VisualUpdateOptions) {
// ...
// if the visual doesn't receive the data no reason to continue rendering
if (!matrixDataView ||
!matrixDataView.columns ||
!matrixDataView.rows ) {
return
}
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// ...
if (matrixNode.children) {
// ...
// traversing child nodes
matrixNode.children.forEach((node, index) => treeWalker(node, index, levels, childDiv));
}
}
// traversing rows
const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
rowRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.rows.levels, this.rowsDiv));
// traversing columns
const colRoot = matrixDataView.columns.root;
colRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.columns.levels, this.colsDiv));
}
// ...
}
Δημιουργήστε τις επιλογές για σημεία δεδομένων.Generate the selections for datapoints.
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// generate selectionID for each node of matrix
const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
.withMatrixNode(matrixNode, levels)
.createSelectionId();
// ...
if (matrixNode.children) {
// ...
// traversing child nodes
matrixNode.children.forEach((node, index) => treeWalker(node, index, levels, childDiv));
}
}
Δημιουργήστε ένα div
για κάθε επίπεδο ιεραρχίας:Create div
for each level of hierarchy:
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// generate selectionID for each node of matrix
const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
.withMatrixNode(matrixNode, levels)
.createSelectionId();
// ...
if (matrixNode.children) {
// create div element for level
const childDiv = document.createElement("div");
// add to current div
div.appendChild(childDiv);
// create paragraph element to display next
const p = document.createElement("p");
// display level name on paragraph element
const level = levels[matrixNode.level];
p.innerText = level.sources[level.sources.length - 1].displayName;
// add paragraph element to created child div
childDiv.appendChild(p);
// traversing child nodes
matrixNode.children.forEach((node, index) => treeWalker(node, index, levels, childDiv));
}
}
Δημιουργία buttons
για αλληλεπίδραση με την απεικόνιση και προβολή του μενού περιβάλλοντος για σημεία δεδομένων μήτρας:Create buttons
to interact with visual and display context menu for matrix datapoints:
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// generate selectionID for each node of matrix
const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
.withMatrixNode(matrixNode, levels)
.createSelectionId();
// create button element
let button = document.createElement("button");
// display node value/name of the button's text
button.innerText = matrixNode.value.toString();
// add event listener on click
button.addEventListener("click", (event) => {
// call select method in the selection manager
this.selectionManager.select(selectionID);
});
// display context menu on click
button.addEventListener("contextmenu", (event) => {
// call showContextMenu method to display context menu on the visual
this.selectionManager.showContextMenu(selectionID, {
x: event.clientX,
y: event.clientY
});
event.preventDefault();
});
div.appendChild(button);
if (matrixNode.children) {
// ...
}
}
Πραγματοποιήστε απαλοιφή των στοιχείων div
προτού αποδώσετε πάλι τα στοιχεία:Clear div
elements before render elements again:
public update(options: VisualUpdateOptions) {
// ...
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// ...
}
// remove old elements
// to better performance use D3js pattern:
// https://d3js.org/#enter-exit
while (this.rowsDiv.firstChild) {
this.rowsDiv.removeChild(this.rowsDiv.firstChild);
}
// create label for row elements
const prow = document.createElement("p");
prow.innerText = "Rows";
this.rowsDiv.appendChild(prow);
while (this.colsDiv.firstChild) {
this.colsDiv.removeChild(this.colsDiv.firstChild);
}
// create label for columns elements
const pcol = document.createElement("p");
pcol.innerText = "Columns";
this.colsDiv.appendChild(pcol);
// render elements for rows
const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
rowRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.rows.levels, this.rowsDiv));
// render elements for columns
const colRoot = matrixDataView.columns.root;
colRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.columns.levels, this.colsDiv));
}
Στο τελικό βήμα θα πρέπει να λάβετε την απεικόνιση με μενού περιβάλλοντος:At the final step you should get visual with context menu:
Επόμενα βήματαNext steps
Για περισσότερες πληροφορίες, ανατρέξτε στο θέμα Κατανόηση της αντιστοίχισης προβολής δεδομένων στις απεικονίσεις Power BI.For more information, see Understand data view mapping in Power BI visuals.