GithubHelp home page GithubHelp logo

microsoft / powerbi-visuals-utils-formattingmodel Goto Github PK

View Code? Open in Web Editor NEW
8.0 6.0 9.0 99 KB

powerbi visuals formatting model helper utils

License: MIT License

TypeScript 98.91% JavaScript 1.09%

powerbi-visuals-utils-formattingmodel's Introduction

Microsoft PowerBI Custom Visuals Formatting Model Utils

FormattingModel utils

Formatting model utils contains the classes, interfaces, and methods needed to build a formatting settings model to populate the property panes (format and analytics panes) of your Power BI custom visual.

Formatting settings service

The formatting settings service receives a formatting settings model, and turns it into a formatting model that populates the formatting pane. The formatting model service also supports string localizations.

Initializing formatting settings service:

import { FormattingSettingsService } from "powerbi-visuals-utils-formattingmodel";

export class MyVisual implements IVisual {
    // declaring formatting settings service 
    private formattingSettingsService: FormattingSettingsService;

    constructor(options: VisualConstructorOptions) {
        
        this.formattingSettingsService = new FormattingSettingsService();
        
        // ...
    }
}

Formatting settings service interface IFormattingSettingsService has two main methods:

    /**
     * Build visual formatting settings model from metadata dataView
     * 
     * @param dataViews metadata dataView object
     * @returns visual formatting settings model 
     */
    populateFormattingSettingsModel<T extends Model>(typeClass: new () => T, dataViews: powerbi.DataView[]): T;

    /**
     * Build formatting model by parsing formatting settings model object 
     * 
     * @returns powerbi visual formatting model
     */
    buildFormattingModel(formattingSettingsModel: Model): visuals.FormattingModel;

Formatting settings model

The settings model contains and wraps all formatting cards for the formatting pane and analytics pane.

export class Model {
    cards: Array<Cards>;
}

This example declares a new formatting settings model:

import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";

import FormattingSettingsCompositeCard = formattingSettings.CompositeCard;
import FormattingSettingsCards = formattingSettings.Cards;
import FormattingSettingsModel = formattingSettings.Model;

export class VisualSettingsModel extends FormattingSettingsModel {
    // Building my visual formatting settings card
    myVisualCard: FormattingSettingsCompositeCard = new myVisualCardSettings();

    // Add formatting settings card to cards list in model
    cards: FormattingSettingsCards[] = [this.myVisualCard];
}

Formatting settings card

A formatting settings card specifies a formatting card in the formatting or analytics pane. A formatting settings card can contain multiple formatting slices, containers, groups, and properties.

Adding slices to a formatting settings card puts all of these slices into one formatting card.

Cards, Slices and Groups can be hidden dynamically by setting the visible parameter to false (true by default)

The card can populate either the formatting pane or analytics pane by setting the analyticsPane parameter to true or false.

Example declaring formatting settings card, including one formatting settings group and slice:

  • Card name should match the object name in capabilities.json
  • Slice name should match the property name in capabilities.json
import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";

import FormattingSettingsCompositeCard = formattingSettings.CompositeCard;
import FormattingSettingsGroup = formattingSettings.Group;
import FormattingSettingsSlice = formattingSettings.Slice;

// Formatting settings group
class myVisualGroupSettings extends FormattingSettingsGroup {
    // Formatting settings slice
    myAnotherNumericSlice = new formattingSettings.NumUpDown({
        name: "myAnotherNumericSlice",
        displayName: "My Formatting Numeric Slice in group",
        value: 15,
        visible: true,
    });

    name: string = "myVisualCard";
    displayName: string = "My Formatting Card";
    analyticsPane: boolean = false;
    visible: boolean = true;
    slices: Array<FormattingSettingsSlice> = [this.myNumericSlice];
}

// Formatting settings card
class myVisualCardSettings extends FormattingSettingsCompositeCard {
    // Formatting settings slice
    myNumericSlice = new formattingSettings.NumUpDown({
        name: "myNumericSlice",
        displayName: "My Formatting Numeric Slice",
        value: 50,
        visible: true,
        options: {
            minValue: {
                type: powerbi.visuals.ValidatorType.Min,
                value: 0,
            },
            maxValue: {
                type: powerbi.visuals.ValidatorType.Max,
                value: 100,
            },
        }
    });

    name: string = "myVisualCard";
    displayName: string = "My Formatting Card";
    analyticsPane: boolean = false;
    visible: boolean = true;

    groupSetting = new myVisualGroupSettings(Object())
    groups: Array<FormattingSettingsGroup> = [this.groupSetting]
    slices: Array<FormattingSettingsSlice> = [this.myNumericSlice];
}

The capabilities.json property declaration should be:

"objects": {
    "myVisualCard": {
        "properties": {
            "myNumericSlice": {
                "type": {
                    "numeric": true 
                }
            },
            "myAnotherNumericSlice": {
                "type": {
                    "numeric": true 
                }
            },
        }
    }
}

Formatting settings group

Some formatting settings cards can have groups inside. Groups consists of slices and can be expanded/collapsed.

Example declaring formatting settings group with one slice:

import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";

import FormattingSettingsGroup = formattingSettings.Group;
import FormattingSettingsSlice = formattingSettings.Slice;

class myVisualGroupSettings extends FormattingSettingsGroup {
    myAnotherNumericSlice = new formattingSettings.NumUpDown({
        name: "myAnotherNumericSlice",
        displayName: "My Formatting Numeric Slice in group",
        value: 15,
        visible: true
    });

    name: string = "myVisualCard";
    displayName: string = "My Formatting Card";
    analyticsPane: boolean = false;
    visible: boolean = true;
    slices: Array<FormattingSettingsSlice> = [this.myNumericSlice];
}

Formatting settings slice

The formatting settings slice type consists of two types of slices - simple and composite.

Each slice contains formatting properties. There's a long list of available formatting properties types.

Example declaring formatting settings slice of type NumUpDown with limitations:

The slice name should match property name from capabilities.json.

    import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";

    myNumericSlice = new formattingSettings.NumUpDown({
        name: "myNumericSlice",
        displayName: "My Formatting Numeric Slice",
        value: 50,
        visible: true,
        options: {
            minValue: {
                type: powerbi.visuals.ValidatorType.Min,
                value: 0,
            },
            maxValue: {
                type: powerbi.visuals.ValidatorType.Max,
                value: 100,
            },
        }
    });

Build formatting pane model using FormattingModel Utils

  1. Open your settings.ts file.
  2. Build your own formatting settings model with all its components (cards, groups, slices, properties ...), and name it VisualFormattingSettings. Replace your settings code with the following:
import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";

import FormattingSettingsCompositeCard = formattingSettings.CompositeCard;
import FormattingSettingsSlice = formattingSettings.Slice;
import FormattingSettingsModel = formattingSettings.Model;

export class VisualSettingsModel extends FormattingSettingsModel {
    // Building my visual formatting settings card
    myVisualCard: FormattingSettingsCard = new myVisualCardSettings();

    // Add formatting settings card to cards list in model
    cards: Array<FormattingSettingsCompositeCard> = [this.myVisualCard];
}

class myVisualCardSettings extends FormattingSettingsCompositeCard {
    myNumericSlice = new formattingSettings.NumUpDown({
        name: "myNumericSlice",
        displayName: "My Formatting Numeric Slice",
        value: 100,
    });

    name: string = "myVisualCard";
    displayName: string = "My Formatting Card";
    analyticsPane: boolean = false;
    slices: Array<FormattingSettingsSlice> = [this.myNumericSlice];
}
  1. In your capabilities file, add your formatting objects and properties
"objects": {
    "myVisualCard": {
        "properties": {
            "myNumericSlice": {
                "type": {
                    "numeric": true 
                }
            }
        }
    }
}
  1. In your visual class, import the following:
import { FormattingSettingsService } from "powerbi-visuals-utils-formattingmodel";
import { VisualFormattingSettingsModel } from "./settings";
  1. Declare formatting settings and formatting settings service
   private formattingSettings: VisualFormattingSettingsModel;
   private formattingSettingsService: FormattingSettingsService;
  1. Initialize the formatting settings service in constructor
constructor(options: VisualConstructorOptions) {
    this.formattingSettingsService = new FormattingSettingsService();

    // ...
}
  1. Build formatting settings in update API using formatting settings service populateFormattingSettingsModel
public update(options: VisualUpdateOptions) {
    this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
    // ...
}
  1. Build formatting model and return it in getFormattingModel API
public getFormattingModel(): powerbi.visuals.FormattingModel {
    return this.formattingSettingsService.buildFormattingModel(this.formattingSettings);
}

Formatting property selector

The optional selector in the formatting properties descriptor determines where each property is bound in the dataView. There are four distinct options.

You can add selector to formatting property in its descriptor object. This example is taken from the SampleBarChart for color custom visual data points using property selectors:

new formattingSettings.ColorPicker({
    name: "fill",
    displayName: dataPoint.category,
    value: { value: dataPoint.color },
    selector: dataViewWildcard.createDataViewWildcardSelector(dataViewWildcard.DataViewWildcardMatchingOption.InstancesAndTotals),
    altConstantSelector: dataPoint.selectionId.getSelector(),
    instanceKind: powerbi.VisualEnumerationInstanceKinds.ConstantOrRule
}

Reset settings to default

Formatting model utils will enable you to reset settings to default by automatically adding all the formatting properties descriptors to the formatting card list of features to revet to default descriptors revertToDefaultDescriptors.

You can enable resetting formatting settings from:

  • The formatting card reset to default button

  • The formatting pane top bar ... -> reset all settings to default button

Localization

For more about the localization feature and to set up localization environment, see Add the local language to your Power BI visual.

Init formatting settings service with localization manager in case localization is required in your custom visual:

constructor(options: VisualConstructorOptions) {

    const localizationManager = options.host.createLocalizationManager();
    this.formattingSettingsService = new FormattingSettingsService(localizationManager);
    
    // ...
}

Add displayNameKey or descriptionKey instead of displayName and description in the appropriate formatting component whenever you want a string to be localized. Example for building a formatting slice with localized display name and description

 myFormattingSlice = new formattingSettings.NumUpDown({
        name: "myFormattingSlice",
        displayNameKey: "myFormattingSlice_Key",
        descriptionKey: "myFormattingSlice_DescriptionKey",
        value: 100
    });

displayNameKey and descriptionKey values should be added to resources.json files.

powerbi-visuals-utils-formattingmodel's People

Contributors

adiletelf avatar alekssavelev avatar asafmozes avatar kulljul avatar liprec avatar microsoft-github-operations[bot] avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar mulyukovaidar avatar pbicvloc avatar shereindabbah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

powerbi-visuals-utils-formattingmodel's Issues

Issues w/ updating to 6.0.1

Hello,

I have run into issues when updating from 5.0.0 to 6.0.0 in an existing project. I have read the readme and changelogs and was not able to solve my issues with these.

First, it is not noted in the changelog nor the readme that populateFormattingSettingsModel has changed its signature.

Before (and what is shown in the readme):
populateFormattingSettingsModel<T extends Model>(typeClass: new () => T, dataViews: powerbi.DataView[]): T;

Current signature:
populateFormattingSettingsModel<T extends Model>(typeClass: new () => T, dataView: powerbi.DataView): T;

Note the change from an array of DataView to a single instance.

This was easily rectified by simply changing the input to the first DataView from the array provided by the Visual (as it seems populateFormattingSettingsModel used to do automatically). But it is still unfortunate the documentation does not reflect the change.

Second, I am getting a TypeError on attempting to read visible.

TypeError: Cannot read properties of null (reading 'visible') at <anonymous>:106666:74 at Array.filter (<anonymous>) at FormattingSettingsService.buildFormattingSlices (<anonymous>:106666:64) at <anonymous>:106644:30 at Array.forEach (<anonymous>) at <anonymous>:106633:46 at Array.forEach (<anonymous>) at <anonymous>:106601:18 at Array.forEach (<anonymous>) at FormattingSettingsService.buildFormattingModel (<anonymous>:106580:14)

This occurs while buildFormattingModel executes. None of my slices or cards have a "visible" property as they are all from before 6.0.0. Since the property is optional, I am surprised I am getting null exceptions on it as it should default to true. Likewise, the compiler does not detect any missing properties on any of my objects.

Containers incompatible with delaySaveSlices true on Cards

delaySaveSlices was added recently, it's a property to cards that adds an "Apply" button that applies all set settings within the card on press. This is especially beneficial in string input settings as, otherwise, the setting change loads very rapidly and can conflict with input typing.

However, it seems that delaySaveSlices is not compatible with containers.

When attempting to change container, it very briefly flashes the new value, but then resets to the prior value.

image

In the image, this happens if I attempt to select "Amount".

I can confirm that it is not just a visual bug in the dropdown. The "Amount" container has different slices and these do not become visible upon switching.

Adding multiple groups to CompositeCard creates duplicates

I am building a Card using two groups and the show toggle. I am extending CompositeCard and my code appears like this:

class AdvancedFormattingSettings extends CompositeCard {
  show = new formattingSettings.ToggleSwitch({
    name: 'show',
    value: false,
    visible: false,
  });

  topLevelSlice = this.show;
  name: string = 'advancedFormatting';
  displayName: string = 'Advanced formatting';
  formatSettingsGroup = new FormatSettingsGroup(Object());
  dropShadowSettingsGroup = new DropShadowSettingsGroup(Object());
  groups: Array<SettingsGroup> = [
    this.formatSettingsGroup,
    this.dropShadowSettingsGroup,
  ];
  slices: Array<SettingsSlice> = [this.show];
}

When I add either group individually, they will be displayed correctly. However when I add both groups using the code above, the groups will be essentially duplicated, as shown.

image

I've inspected the settingsModel after it's populated in the update method, and it appears as expected. There is no duplication. This duplication only appears in the UI.

I'm using 6.0.1 and developing in the web app.

Unable to enable Apply Button for delaySaveSlices while modifying controls

I am encountering an issue with the delaySaveSlices functionality in a group that includes a slider, color picker, and text area. Sometimes, when I modify the values of these components, the "Apply" button does not get enabled as expected.

Here's an example:
delaySaveSlices

Here's the sample code of my FormattingGroup :

const groups: powerbi.visuals.FormattingGroup = {
        displayName: "",
        uid: `datacard_groups`,
        delaySaveSlices: true,
        slices: [
            {
                displayName: "Text",
                description: "",
                uid: `datacard_groups_text`,
                control: {
                    type: FormattingComponent.TextArea,
                    properties: {
                        placeholder: "Text",
                        descriptor: {
                            objectName: "groups",
                            propertyName: `text`,
                        },
                        value: settings.groups.text,
                    },
                },
            },
            {
                displayName: "Color",
                description: "",
                uid: `datacard_groups_color`,
                control: {
                    type: FormattingComponent.ColorPicker,
                    properties: {
                        descriptor: {
                            objectName: "groups",
                            propertyName: `color`,
                        },
                        value: { value: settings.groups.text},
                    },
                },
            },
            ...
            {
                displayName: "Opacity",
                description: "",
                uid: "datacard_groups_opacity",
                control: {
                    type: FormattingComponent.Slider,
                    properties: {
                        descriptor: {
                            objectName: "groups",
                            propertyName: "opacity",
                        },
                        value: settings.groups.opacity,
                        options: {
                            maxValue: {
                                type:  powerbi.visuals.ValidatorType.Max,
                                value: 100,
                            },
                            minValue: {
                                type:  powerbi.visuals.ValidatorType.Min,
                                value: 1,
                            },
                        },
                    },
                }
            }
        ],
    };

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.