Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Added bookmarks support #6

Merged
merged 4 commits into from
Apr 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ pbiviz start
3. Advanced selection with the Advanced Filter API
- [Adding the Advanced Filter API to the project](doc/AddingAdvancedFilterAPI.md)
- [Using the Advanced Filter API](doc/UsingAdvancedFilterAPI.md)
4. Bookmarks support
- [Adding bookmarks support to the project](doc/AddingBookmarksSuppoprt.md)
73 changes: 73 additions & 0 deletions doc/AddingBookmarksSuppoprt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Adding bookmarks support to the project

The main documentation about bookmarks can be found [here](https://github.com/Microsoft/PowerBI-visuals/blob/master/Tutorial/BookmarksSupport.md).

To add bookmarks support for the visual, you should update to version 3.0.0 or higher of `powerbi-visuals-utils-interactivityutils`.

In the update `updateOnRangeSelectonChange` method the visual creates an AdvancedFilter and applies the filter with one or two conditions and calls `applyAdvancedFilter`, where `applyAdvancedFilter` [calls](https://github.com/Microsoft/powerbi-visuals-sampleslicer/blob/master/src/sampleSlicer.ts#L795) `this.visualHost.applyJsonFilter` method.

In each update the visual [inspects and restores](https://github.com/Microsoft/powerbi-visuals-sampleslicer/pull/6/files#diff-5929da3be6a696fb9df5e3571baceb52R356) the persisted filter by using [`FilterManager.restoreFilter`](https://github.com/Microsoft/PowerBI-visuals/blob/master/Tutorial/BookmarksSupport.md#visuals-with-filter).

```typescript
private restoreFilter(data: SampleSlicerData) {
// restore advanced filter from visual properties
let restoredFilter: IAdvancedFilter =
FilterManager.restoreFilter(data && data.slicerSettings.general.filter) as IAdvancedFilter;
// if filter was persisted, the visual retrieves the conditions of the advanced filter
if (restoredFilter) {
restoredFilter.target = this.getCallbacks().getAdvancedFilterColumnTarget();
// reset to default
// modify the values to match the filter values
// in some cases we can receive values with only one condition
if (restoredFilter.conditions.length === 1) {
let value: {
max?: any,
min?: any
} = {};

// get min and max values in the dataset
let convertedValues = data.slicerDataPoints.map( (dataPoint: SampleSlicerDataPoint) => +dataPoint.category );
value.min = d3.min(convertedValues);
value.max = d3.max(convertedValues);

// if some conditions is missing, the visual adds the condition with matching value
let operator = restoredFilter.conditions[0].operator;
if (operator === "LessThanOrEqual" || operator === "LessThan") {
restoredFilter.conditions.push({
operator: "GreaterThan",
value: value.min
});
}
if (operator === "GreaterThanOrEqual" || operator === "GreaterThan") {
restoredFilter.conditions.push({
operator: "LessThan",
value: value.max
});
}
}

// create ValueRange object to apply current filter state to the slicer visual
let rangeValue: ValueRange<number> = <ValueRange<number>>{};

restoredFilter.conditions.forEach( (condition: IAdvancedFilterCondition) => {
let value = condition.value;
let operator = condition.operator;
if (operator === "LessThanOrEqual" || operator === "LessThan") {
rangeValue.max = <number>value;
}
if (operator === "GreaterThanOrEqual" || operator === "GreaterThan") {
rangeValue.min = <number>value;
}
});

// change visual state of slicer
this.behavior.scalableRange.setValue(rangeValue);
// change visual state of text boxes
this.onRangeInputTextboxChange(rangeValue.min.toString(), RangeValueType.Start);
this.onRangeInputTextboxChange(rangeValue.max.toString(), RangeValueType.End);
}
}
```
Resuming: in this method the visual restores the `restoredFilter` object, parses conditions for restoring saved values of the slicer and applies values to slicer and text boxes.

You **should not** persist the filter in the visual properties. Because Power BI saves filter for the visual. And `persistSelectionState`, `restorePersistedRangeSelectionState` and other methods [were removed](https://github.com/Microsoft/powerbi-visuals-sampleslicer/pull/6/files#diff-5929da3be6a696fb9df5e3571baceb52L809).
5 changes: 1 addition & 4 deletions doc/UsingInteractivityUtils.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ For <b>discrete</b> cross-visual data-point selection the Sample Slicer visual r

ISelectionHandler holds the state of all discrete (possibly multiple) data-point selections. The handler is updated on each data-point selection event (each mouse click) and does NOT automatically propagate the event to the hosting application. The selection state is only propagated to the host when the method ISelectionHandler.applySelectionFilter() is invoked.

Below is the code executed on each slicer mouse click. The handler is updated with the select/unselect data point event and the complete discrete selection state is flushed to the hosting application. Additionally, the selection state is persisted to the visual's properties so the next time the visual is loaded the selection can be restored.
Below is the code executed on each slicer mouse click. The handler is updated with the select/unselect data point event and the complete discrete selection state is flushed to the hosting application. Additionally, the selection state is persisted to the visual's properties as applyed filter, so the next time the visual is loaded the selection can be restored.

```
/* update selection state */
selectionHandler.handleSelection(dataPoint, true /* isMultiSelect */);

/* send selection state to the host*/
selectionHandler.applySelectionFilter();

/*persiste selection state to properties */
this.persistSelectionState();
```

An instance implementing ISelectionHandler interface is created by InteractivityUtils and supplied to SelectionBehavior class as an argument of SelectionBehavior::bindEvents() method call.
Loading