透過 Power BI 視覺效果選取項目,將互動功能新增至視覺效果中
Power BI 提供兩種方式來與視覺效果互動 - 選取和篩選。 以下範例示範如何從一個視覺效果中選取一個項目,並通知報表中的其他視覺效果有關新的選取項目狀態。
介面會對應至 Selection
物件:
export interface ISelectionId {
equals(other: ISelectionId): boolean;
includes(other: ISelectionId, ignoreHighlight?: boolean): boolean;
getKey(): string;
getSelector(): Selector;
getSelectorsByColumn(): SelectorsByColumn;
hasIdentity(): boolean;
}
使用選取項目管理員來選取資料點
視覺效果主機物件提供了建立選取項目管理員執行個體的方法。 選取項目管理員對於以下每個動作都有對應的方法:
- 選取
- 清除選取項目
- 顯示操作功能表
- 儲存目前的選取項目
- 檢查選取項目狀態
建立選取項目管理員的執行個體
若要使用選取項目管理員,請建立選取項目管理員的執行個體。 通常,視覺效果會在視覺效果物件的 constructor
區段中建立一個選取項目管理員執行個體。
export class Visual implements IVisual {
private target: HTMLElement;
private host: IVisualHost;
private selectionManager: ISelectionManager;
// ...
constructor(options: VisualConstructorOptions) {
this.host = options.host;
// ...
this.selectionManager = this.host.createSelectionManager();
}
// ...
}
建立選取項目產生器的執行個體
建立選取項目管理員執行個體時,您必須為視覺效果的每個資料點都建立 selections
。 視覺主機物件的 createSelectionIdBuilder
方法會為每個資料點產生選取項目。 此方法會傳回一個具有介面 powerbi.visuals.ISelectionIdBuilder
之物件的執行個體:
export interface ISelectionIdBuilder {
withCategory(categoryColumn: DataViewCategoryColumn, index: number): this;
withSeries(seriesColumn: DataViewValueColumns, valueColumn: DataViewValueColumn | DataViewValueColumnGroup): this;
withMeasure(measureId: string): this;
withMatrixNode(matrixNode: DataViewMatrixNode, levels: DataViewHierarchyLevel[]): this;
withTable(table: DataViewTable, rowIndex: number): this;
createSelectionId(): ISelectionId;
}
此物件具有對應的方法來為不同類型的資料檢視對應建立 selections
。
注意
方法 withTable
和 withMatrixNode
是在 Power BI 視覺效果的 API 2.5.0 中引進。
如果您需要針對資料表或矩陣資料檢視對應使用選取項目,請更新至 API 2.5.0 版或更高版本。
建立類別資料檢視對應的選取項目
讓我們來檢閱選取項目如何呈現範例語意模型的分類資料檢視對應:
製造商 | 類型 | 值 |
---|---|---|
克萊斯勒 | 國內車輛 | 28883 |
克萊斯勒 | 國內卡車 | 117131 |
克萊斯勒 | 進口車輛 | 0 |
克萊斯勒 | 進口卡車 | 6362 |
Ford | 國內車輛 | 50032 |
Ford | 國內卡車 | 122446 |
Ford | 進口車輛 | 0 |
Ford | 進口卡車 | 0 |
GM | 國內車輛 | 65426 |
GM | 國內卡車 | 138122 |
GM | 進口車輛 | 197 |
GM | 進口卡車 | 0 |
Honda | 國內車輛 | 51450 |
Honda | 國內卡車 | 46115 |
Honda | 進口車輛 | 2932 |
Honda | 進口卡車 | 0 |
Nissan | 國內車輛 | 51476 |
Nissan | 國內卡車 | 47343 |
Nissan | 進口車輛 | 5485 |
Nissan | 進口卡車 | 1430 |
Toyota | 國內車輛 | 55643 |
Toyota | 國內卡車 | 61227 |
Toyota | 進口車輛 | 20799 |
Toyota | 進口卡車 | 23614 |
視覺效果會使用下列資料檢視對應:
{
"dataRoles": [
{
"displayName": "Columns",
"name": "columns",
"kind": "Grouping"
},
{
"displayName": "Rows",
"name": "rows",
"kind": "Grouping"
},
{
"displayName": "Values",
"name": "values",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "columns"
}
},
"values": {
"group": {
"by": "rows",
"select": [
{
"for": {
"in": "values"
}
}
]
}
}
}
}
]
}
在上述範例中,Manufacturer
是 columns
,而 Type
是 rows
。 按 rows
對值進行分組來建立數列 (Type
)。
視覺效果應該能夠按 Manufacturer
或 Type
來分割資料。
例如,如果使用者按 Manufacturer
選取 Chrysler
,則其他視覺效果應該會顯示下列資料:
製造商 | 類型 | 值 |
---|---|---|
克萊斯勒 | 國內車輛 | 28883 |
克萊斯勒 | 國內卡車 | 117131 |
克萊斯勒 | 進口車輛 | 0 |
克萊斯勒 | 進口卡車 | 6362 |
當使用者按 Type
選取 Import Car
(依數列選取資料) 時,則其他視覺效果應該會顯示以下資料:
製造商 | 類型 | 值 |
---|---|---|
克萊斯勒 | 進口車輛 | 0 |
Ford | 進口車輛 | 0 |
GM | 進口車輛 | 197 |
Honda | 進口車輛 | 2932 |
Nissan | 進口車輛 | 5485 |
Toyota | 進口車輛 | 20799 |
若要顯示分割的資料,請填入視覺效果的資料籃,如下所示:
在上述範例中,Manufacturer
是類別 (資料行)、Type
是數列 (資料列),而 Sales
是數列的 Values
。
注意
顯示數列時需要 Values
,因為根據資料檢視對應,Values
會按 Rows
資料分組。
建立類別的選取項目
// categories
const categories = dataView.categorical.categories;
// create label for 'Manufacturer' column
const p = document.createElement("p") as HTMLParagraphElement;
p.innerText = categories[0].source.displayName.toString();
this.target.appendChild(p);
// get count of category elements
const categoriesCount = categories[0].values.length;
// iterate all categories to generate selection and create button elements to use selections
for (let categoryIndex = 0; categoryIndex < categoriesCount; categoryIndex++) {
const categoryValue: powerbi.PrimitiveValue = categories[0].values[categoryIndex];
const categorySelectionId = this.host.createSelectionIdBuilder()
.withCategory(categories[0], categoryIndex) // we have only one category (only one `Manufacturer` column)
.createSelectionId();
this.dataPoints.push({
value: categoryValue,
selection: categorySelectionId
});
console.log(categorySelectionId);
// create button element to apply selection on click
const button = document.createElement("button") as HTMLButtonElement;
button.value = categoryValue.toString();
button.innerText = categoryValue.toString();
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(categorySelectionId);
});
this.target.appendChild(button);
}
在上述範例程式碼中,我們會逐一查看所有類別。 在每次反覆運算中,我們都會透過呼叫選取項目建立器的 withCategory
方法來呼叫 createSelectionIdBuilder
以建立每個類別的下一個選取項目。 createSelectionId
方法會用作傳回所產生之 selection
物件的最後方法。
在 withCategory
方法中,我們會傳遞 category
的資料行,在範例中,它的 Manufacturer
和類別元素的索引。
建立數列的選取項目
// get groupped values for series
const series: powerbi.DataViewValueColumnGroup[] = dataView.categorical.values.grouped();
// create label for 'Type' column
const p2 = document.createElement("p") as HTMLParagraphElement;
p2.innerText = dataView.categorical.values.source.displayName;
this.target.appendChild(p2);
// iterate all series to generate selection and create button elements to use selections
series.forEach( (ser: powerbi.DataViewValueColumnGroup) => {
// create selection id for series
const seriesSelectionId = this.host.createSelectionIdBuilder()
.withSeries(dataView.categorical.values, ser)
.createSelectionId();
this.dataPoints.push({
value: ser.name,
selection: seriesSelectionId
});
// create button element to apply selection on click
const button = document.createElement("button") as HTMLButtonElement;
button.value =ser.name.toString();
button.innerText = ser.name.toString();
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(seriesSelectionId);
});
this.target.appendChild(button);
});
建立資料表資料檢視對應的選取項目
下列範例顯示資料表資料檢視對應:
{
"dataRoles": [
{
"displayName": "Values",
"name": "values",
"kind": "GroupingOrMeasure"
}
],
"dataViewMappings": [
{
"table": {
"rows": {
"for": {
"in": "values"
}
}
}
}
]
}
若要為資料表資料檢視對應的每個資料列建立選取項目,請呼叫選取項目建立器的 withTable
方法。
public update(options: VisualUpdateOptions) {
const dataView = options.dataViews[0];
dataView.table.rows.forEach((row: DataViewTableRow, rowIndex: number) => {
this.target.appendChild(rowDiv);
const selection: ISelectionId = this.host.createSelectionIdBuilder()
.withTable(dataView.table, rowIndex)
.createSelectionId();
}
}
視覺效果程式碼會逐一查看資料表的資料列,而每個資料列都會呼叫 withTable
資料表方法。 withTable
方法的參數是 table
物件和資料表資料列的索引。
建立矩陣資料檢視對應的選取項目
public update(options: VisualUpdateOptions) {
const host = this.host;
const rowLevels: powerbi.DataViewHierarchyLevel[] = dataView.matrix.rows.levels;
const columnLevels: powerbi.DataViewHierarchyLevel[] = dataView.matrix.rows.levels;
// iterate rows hierarchy
nodeWalker(dataView.matrix.rows.root, rowLevels);
// iterate columns hierarchy
nodeWalker(dataView.matrix.columns.root, columnLevels);
function nodeWalker(node: powerbi.DataViewMatrixNode, levels: powerbi.DataViewHierarchyLevel[]) {
const nodeSelection = host.createSelectionIdBuilder().withMatrixNode(node, levels);
if (node.children && node.children.length) {
node.children.forEach(child => {
nodeWalker(child, levels);
});
}
}
}
在範例中,nodeWalker
會遞歸呼叫每個節點和子節點。
nodeWalker
會在每個呼叫上建立 nodeSelection
物件。 每個 nodeSelection
都代表對應節點的 selection
。
選取資料點以分割其他視覺效果
在此範例中,我們為按鈕元素建立了一個點擊處理常式。 此處理常式會呼叫選取項目管理員的 select
方法,並傳遞選取項目物件。
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(categorySelectionId);
});
select
方法的介面:
interface ISelectionManager {
// ...
select(selectionId: ISelectionId | ISelectionId[], multiSelect?: boolean): IPromise<ISelectionId[]>;
// ...
}
select
方法可以接受選取項目的陣列。 這可讓您的視覺效果一次選取數個資料點。 第二個參數 multiSelect
負責多重選取。 如果 multiSelect
為 true,則 Power BI 在套用目前的選取項目時不會清除先前的選取項目狀態。 如果值為 false,則會覆寫先前的選取項目。
使用 multiSelect
的一個典型範例是處理點擊事件上的 Ctrl 按鈕狀態。 當按住 Ctrl 按鈕時,您可以選取多個物件。
button.addEventListener("click", (mouseEvent) => {
const multiSelect = (mouseEvent as MouseEvent).ctrlKey;
this.selectionManager.select(seriesSelectionId, multiSelect);
});