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

Preparing for a certification exam? Ask exam experts all your questions on May 15th. Register now.

Reply
TheMoM
Regular Visitor

Issue with filtering not working after pbiviz package in Power BI Custom Visual

Hello Power BI Community,

I am experiencing an issue with a custom Power BI visual that I am developing
. The visual works perfectly during development when using pbiviz start, but after packaging it using pbiviz package, the filtering functionality does not work at all, no values are modified in the report where I m using it because of the filtering.

There are no errors or missing steps shown in the console related to the filtering
. In picture you have my applydatefilter function that I use for the filtering in my custom visual if you want to check.

image.png


Has anyone encountered a similar issue with Power BI custom visuals
? What could be the possible reasons for this discrepancy between development and packaged visual behavior?

Thank you in advance for your assistance!

2 REPLIES 2
Anonymous
Not applicable

Hi @TheMoM,

What type of filter effects not works? The default visual filter or the custom filter effects? Can you please share some more detail about these?

How to Get Your Question Answered Quickly  

Regards,

Xiaoxin Sheng

The visual of the filter work well, what  does not work is the filter when I m using pbiviz package which means when modifying the dates, the other data in the report does not change, but somehow this problem is not present when using pbiviz start to show the visual.  I m also thinking right now that the problem is not in the filter function, so I will give you my entire visual.ts code if you want to check. Also, the console.log will not help me to find the error because when using it every function seem to work fine.

Here’s my visual.ts code :


"use strict";

// Import necessary libraries and styles
import "core-js/stable";
import "regenerator-runtime/runtime";
import './../style/visual.less';
import 'bootstrap-slider/dist/css/bootstrap-slider.min.css';
import Slider from 'bootstrap-slider';
import * as $ from 'jquery';
import powerbi from "powerbi-visuals-api";

// Import Power BI types
import DataView = powerbi.DataView;
import IVisualHost = powerbi.extensibility.IVisualHost;
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import { AdvancedFilter, IFilterColumnTarget } from "powerbi-models";

// Import settings model
import { VisualFormattingSettingsModel } from "./settings";

// Interface for date range data points
interface DateRangeDataPoint {
category: string;
minDate: string;
maxDate: string;
}

// Main Visual class
export class Visual implements powerbi.extensibility.visual.IVisual {
private target: HTMLElement;
private host: IVisualHost;

private dateRangeContainer: HTMLDivElement;
private dateInputStart: HTMLInputElement;
private dateInputEnd: HTMLInputElement;
private sliderElement: HTMLInputElement;
private sliderInstance: Slider;

private settings: VisualFormattingSettingsModel;
private minDateValue: number;
private maxDateValue: number;
private isApplyingFilter: boolean = false;
private lastAppliedStartDate: string;
private lastAppliedEndDate: string;

// Constructor
constructor(options: VisualConstructorOptions) {
this.target = options.element;
this.host = options.host;

// Create date range container and inputs
this.dateRangeContainer = document.createElement('div');
this.dateRangeContainer.className = 'date-range-container';

this.dateInputStart = document.createElement('input');
this.dateInputStart.type = 'date';
this.dateInputStart.className = 'date-input';

this.dateInputEnd = document.createElement('input');
this.dateInputEnd.type = 'date';
this.dateInputEnd.className = 'date-input';

this.sliderElement = document.createElement('input');
this.sliderElement.type = 'text';
this.sliderElement.className = 'slider';

this.dateRangeContainer.appendChild(this.dateInputStart);
this.dateRangeContainer.appendChild(this.dateInputEnd);

this.target.appendChild(this.dateRangeContainer);
this.target.appendChild(this.sliderElement);

this.initializeSlider();

// Add event listeners to date inputs
this.dateInputStart.addEventListener('change', () => this.onDateInputChange());
this.dateInputEnd.addEventListener('change', () => this.onDateInputChange());
}

// Initialize the slider
private initializeSlider() {
this.sliderInstance = new Slider(this.sliderElement, {
min: 0,
max: 100,
value: [0, 100],
tooltip: 'hide',
tooltip_split: false
});

// Add event listener for slider stop event
this.sliderInstance.on('slideStop', (event) => {
const values = this.sliderInstance.getValue();
const minDate = values[0];
const maxDate = values[1];
this.dateInputStart.value = new Date(minDate).toISOString().split('T')[0];
this.dateInputEnd.value = new Date(maxDate).toISOString().split('T')[0];
this.applyDateFilter(this.dateInputStart.value, this.dateInputEnd.value);
});
}

// Update slider range
private updateSliderRange(minDateValue: number, maxDateValue: number) {
if (this.minDateValue !== minDateValue || this.maxDateValue !== maxDateValue) {
this.sliderInstance.setAttribute('min', minDateValue);
this.sliderInstance.setAttribute('max', maxDateValue);
this.sliderInstance.setValue([minDateValue, maxDateValue]);

this.dateInputStart.value = new Date(minDateValue).toISOString().split('T')[0];
this.dateInputEnd.value = new Date(maxDateValue).toISOString().split('T')[0];

// Save the new values to prevent unnecessary updates
this.minDateValue = minDateValue;
this.maxDateValue = maxDateValue;
}
}

// Update function called by Power BI
public async update(options: VisualUpdateOptions) {
if (this.isApplyingFilter) {
return;
}

if (options.dataViews && options.dataViews[0]) {
const dataView: DataView = options.dataViews[0];
const dateRangeDataPoints = this.createSelectorDataPoints(options, this.host);

if (dateRangeDataPoints.length > 0) {
const newMinDateValue = new Date(dateRangeDataPoints[0].minDate).getTime();
const newMaxDateValue = new Date(dateRangeDataPoints[0].maxDate).getTime();

if (newMinDateValue !== this.minDateValue || newMaxDateValue !== this.maxDateValue) {
this.updateSliderRange(newMinDateValue, newMaxDateValue);
this.applyDateFilter(this.dateInputStart.value, this.dateInputEnd.value);

// Sleep for 10 seconds to prevent re-entrant calls
await new Promise((resolve) => setTimeout(resolve, 10000));
}
} else {
this.clear();
}
} else {
this.clear();
}
}

// Create selector data points from data view
private createSelectorDataPoints(options: VisualUpdateOptions, host: IVisualHost): DateRangeDataPoint[] {
const dateRangeDataPoints: DateRangeDataPoint[] = [];
const dataViews = options.dataViews;

if (!dataViews || !dataViews[0]) {
return dateRangeDataPoints;
}

const dataView = dataViews[0];
if (!dataView.categorical) {
return dateRangeDataPoints;
}

const categorical = dataView.categorical;
if (!categorical.categories || !categorical.values) {
return dateRangeDataPoints;
}

const category = categorical.categories[0];
const minDateValue = categorical.values[0];
const maxDateValue = categorical.values[1];

if (!category || !minDateValue || !maxDateValue) {
return dateRangeDataPoints;
}

// Assuming you only need the first value
dateRangeDataPoints.push({
category: `${category.values[0]}`,
minDate: this.ensureDateFormat(`${minDateValue.values[0]}`),
maxDate: this.ensureDateFormat(`${maxDateValue.values[0]}`)
});

return dateRangeDataPoints;
}

// Ensure date format is correct
private ensureDateFormat(dateString: string): string {
const date = new Date(dateString);
return date.toISOString().split('.')[0] + "Z";
}

// Clear the visual
private clear() {
this.sliderInstance.setValue([0, 100]);
this.dateInputStart.value = "";
this.dateInputEnd.value = "";
}

// Event handler for date input change
private onDateInputChange() {
const startDate = new Date(this.dateInputStart.value).getTime();
const endDate = new Date(this.dateInputEnd.value).getTime();
this.sliderInstance.setValue([startDate, endDate]);
this.applyDateFilter(this.dateInputStart.value, this.dateInputEnd.value);
}

// Apply date filter
private async applyDateFilter(startDate: string, endDate: string): Promise<void> {
if (this.lastAppliedStartDate === startDate && this.lastAppliedEndDate === endDate) {
return;
}

this.lastAppliedStartDate = startDate;
this.lastAppliedEndDate = endDate;

const target: IFilterColumnTarget = {
table: "document",
column: "document_creation_date"
};

const filter = new AdvancedFilter(target, "And", [
{
operator: "GreaterThanOrEqual",
value: this.ensureDateFormat(startDate)
},
{
operator: "LessThanOrEqual",
value: this.ensureDateFormat(endDate)
}
]);

this.isApplyingFilter = true;
(this.host as any).applyJsonFilter(
filter,
"dataPoint",
"filter",
powerbi.FilterAction.merge
);
this.isApplyingFilter = false;}
}

Helpful resources

Announcements
PBIApril_Carousel

Power BI Monthly Update - April 2025

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

Notebook Gallery Carousel1

NEW! Community Notebooks Gallery

Explore and share Fabric Notebooks to boost Power BI insights in the new community notebooks gallery.

April2025 Carousel

Fabric Community Update - April 2025

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