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

Enhance your career with this limited time 50% discount on Fabric and Power BI exams. Ends August 31st. Request your voucher.

Reply
emilerobi
Frequent Visitor

Filtering other visuals with my custom visual

 

Hello,

 

I am working on creating a custom visual in Power BI using React. I have been following a tutorial provided by the Microsoft team, and I've successfully implemented the process of sending data from Power BI to my application. Now, I am looking to understand how to send signals from the custom visuals to other visuals. In my exploration, I came across documentation related to 'Host,' 'createSelectionIdBuilder,' and 'createSelectionManager.

 

While I have already written some code, I am struggling with how to effectively integrate these concepts into my React-based custom visual. If you have any insights or guidance on this matter, I would greatly appreciate it.

 

capabilities.json file

 

{
  "dataRoles": [
    {
      "displayName": "Target Values",
      "name": "CheckMarksDropDown",
      "kind": "Grouping"
    }
  ],
  "dataViewMappings": [
    {
      "conditions": [
        {
          "CheckMarksDropDown": {
            "min": 1,
            "max": 1
          }
        }
      ],
      "categorical": {
        "categories": {
          "for": {
            "in": "CheckMarksDropDown"
          }
        }
      }
    }
  ],
  "privileges": []
}

 

 

 

visual.ts

 

 

 

"use strict";
import powerbi from "powerbi-visuals-api";

import DataView = powerbi.DataView;
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  initialState,
  CheckMarksDropDown,
} from "./components/CheckMarksDropDown";
import "./../style/visual.less";

export class Visual implements IVisual {
  private target: HTMLElement;
  private host: powerbi.extensibility.visual.IVisualHost;
  private reactRootElement: React.ComponentElement<any, any>;
  private selectionManager: powerbi.extensibility.ISelectionManager;

  constructor(options: VisualConstructorOptions) {
    this.target = options.element;
    this.reactRootElement = React.createElement(CheckMarksDropDown, {
      state: initialState,
      onSelect: this.onSelect.bind(this),
    });

    this.selectionManager = options.host.createSelectionManager();
    this.selectionManager.registerOnSelectCallback(this.onSelect.bind(this));

    ReactDOM.render(this.reactRootElement, this.target);
  }

  public update(options: VisualUpdateOptions) {
    console.log({ "Update options": options });
    const dataView: DataView = options?.dataViews[0];

    if (dataView) {
      const targetValues = dataView.categorical.categories[0].values;
      CheckMarksDropDown.update({
        title: "Zero After Zero",
        target: targetValues,
      });
    } else {
      this.clear();
    }
  }

  private onSelect(selectionId: powerbi.extensibility.ISelectionId) {
    console.log("Selected DP", selectionId);
  }

  private clear() {
    CheckMarksDropDown.update(initialState);
  }
}

 

 

CheckMarksDropDown.tsx

 

import { Box, Select, MenuItem, Checkbox, ListItemText } from "@mui/material";
import * as React from "react";

export interface CheckMarksDropDownProps<T> {
  target?: T[];
  title?: string;
  selectedValues?: T[];
  onSelect?: (selectionId: powerbi.extensibility.ISelectionId) => void;
}

export const initialState = {
  title: "",
  target: [],
  selectedValues: [],
};

export class CheckMarksDropDown extends React.Component<
  CheckMarksDropDownProps<any>,
  CheckMarksDropDownProps<any>
> {
  constructor(props) {
    super(props);
    this.state = initialState;
  }

  private static updateCallback: (data: object) => void = null;

  public static update = (newState: CheckMarksDropDownProps<any>) => {
    if (typeof CheckMarksDropDown.updateCallback === "function") {
      CheckMarksDropDown.updateCallback(newState);
    }
  };

  public componentDidMount(): void {
    CheckMarksDropDown.updateCallback = (
      newState: CheckMarksDropDownProps<any>
    ) => {
      this.setState(newState);
    };
  }

  componentWillUnmount(): void {
    CheckMarksDropDown.updateCallback = null;
  }

  render() {
    const { title, target, selectedValues } = this.state;
    const handleChange = (event) => {
      const {
        target: { value },
      } = event;
      this.props.onSelect(value);
      this.setState((prevState) => ({
        ...prevState,
        selectedValues: value,
      }));
    };

    return (
      <div>
        <Box sx={{ my: 2, fontSize: "2vw" }}>{title}</Box>
        <Box sx={{ minWidth: 200 }}>
          <Select
            multiple
            fullWidth
            value={selectedValues}
            onChange={handleChange}
            renderValue={(selected) => selected.join(", ")}
            MenuProps={{
              PaperProps: {
                style: {
                  left: "0 !important",
                },
              },
            }}
          >
            {target &&
              target.map((value) => (
                <MenuItem divider key={value} value={value}>
                  <Checkbox checked={selectedValues.indexOf(value) > -1} />
                  <ListItemText primary={value} />
                </MenuItem>
              ))}
          </Select>
        </Box>
      </div>
    );
  }
}

Thank you!

0 REPLIES 0

Helpful resources

Announcements
July 2025 community update carousel

Fabric Community Update - July 2025

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

July PBI25 Carousel

Power BI Monthly Update - July 2025

Check out the July 2025 Power BI update to learn about new features.

Top Solution Authors