Modify a filter / view parameter using scripting

Contents[Hide]

1. Overview

The goal of this article is to outline the differences between view parameters and how to change the selected values of those view parameters.

2. Prerequisites

  • Intermediate understanding of JavaScript

3. Understanding

3.1. What is a View Parameter

A view parameter acts as a connection or a bridge between the filter control and the visualization. You can have a view parameter without having a filter control, and you can have a filter control without a view paremter. There are various use cases where this becomes valuable. You can view all the existing and create new parameters in the Parameters tab located at the bottom of the designer window.

3.2. What are the types of View Parameters

According to our JavaScript API documentation, these are the available parameter value types:
SingleDateTime, SingleMember, SingleBoolean, SingleString, SingleNumber, RangeDateTime, RangeMember, RangeNumber, RangeString, Logical, HierarchyLevel, MemberDrillDown, Referenced, File, TimeHierarchyOffset, ConnectorElement, AnalysisElement, CollectionDateTime, CollectionMember, CollectionNumber, CollectionString, CollectionBoolean, AllDateTimeValues, AllNumberValues, AllStringValues, AllHierarchyValues

Below is a list of the parameter types we will be covering in this article:

3.3. What are Tokens?

Tokens are predefined values that can be accessed using the white triangle to the right of the filter control. The values presented in the token dropdown list will depend on the data type. If the data type is of a time hierarchy, the list will have various convenient choices such as: Today, Current Month, Previous Year, End of Year, etc. 

Note
Using a range token in a single date/time filter will default to the beginning of that range (e.g. Current Year will be January 1st of that year).

4. Setup

4.1. Ready action script

We will be using a couple helper functions for this article. In the code below, the functions are stored in a Library attached to the window object which is a globally accessable object. Placing the below code in the 'Ready' action of the dashboard will allow you to access these functions from anywhere.

window.myLib = {
    // Returns a single adapter with matching name
    // Example: myLibrary.getAdapterByName("chart2");
    getAdapterByName: function (name) {
        var view = dundas.context.baseViewService.currentView;
        return view.getAdapters().toEnumerable().first(function (a) {
            return a.name === name;
        });
    },

    // Returns a single view parameter with matching name
    // Example: myLibrary.getViewParameterByName("viewParameter1");
    getViewParameterByName: function (name) {
        var view = dundas.context.baseViewService.currentView;
        return view.control.viewParameters.toEnumerable().first(function (vp) {
            return vp.name === name;
        });
    }
};

5. Parameters values and Token values

5.1. RangeNumber

// Using the library, get the view parameter based on it's name
var myVP = myLib.getViewParameterByName("viewParameter1");

// Remove all values and tokens from the parameter value
myVP.parameterValue.clearTokens();
myVP.parameterValue.clearValues();

// Set the lower and upper values
myVP.parameterValue.lowerBoundaryValue = 100;
myVP.parameterValue.upperBoundaryValue = 200;

// Sets the value of lastModifiedTime to now
myVP.invalidateParameterValueLastModifiedTime();

// Update all the connected adapters with the newly modified values
// Includes data visualizations and filter controls
myVP.refreshAllAdapters();

5.2. HierarchyLevel

// Using the library, get the view parameter based on it's name
var myVP = myLib.getViewParameterByName("viewParameter1");

// Set the depth of the hierarchy to be displayed
myVP.paramet0erValue.detailsLevelDepth = 1;

// Set the top level if you wish to display more than 1 level
// Default is -1 which will use the details level depth instead
myVP.parameterValue.topLevelDepth = 0;

// Sets the value of lastModifiedTime to now
myVP.invalidateParameterValueLastModifiedTime();

// Update all the connected adapters with the newly modified values
// Includes data visualizations and filter controls
myVP.refreshAllAdapters();

5.3. TimeHierarchyOffset

// Using the library, get the view parameter based on it's name
var myVP = myLib.getViewParameterByName("viewParameter1");

// Set the offset of the Period over Period to be displayed
// Negative values will set the offset 'Backward'
myVP.parameterValue.offset = -1;

// Level value format = "Level.Code.TimeDimensionName"
// Day=0  Week=1  Month=2  Quarter=3  Half=4  Year=5
// Example: "2.54320.DueDate"

// Only modify the level index by taking a substring 
var str = myVP.parameterValue.level;
var endOfLevel = str.substring(str.indexOf('.'));

// Set the level to the level number and concatinate endOfLevel
myVP.parameterValue.level = "5" + endOfLevel;
// This will result in Backwards 1 Year

// Sets the value of lastModifiedTime to now
myVP.invalidateParameterValueLastModifiedTime();

// Update all the connected adapters with the newly modified values
// Includes data visualizations and filter controls
myVP.refreshAllAdapters();

5.4. CollectionMember

// Using the library, get the view parameter based on it's name
var myVP = myLib.getViewParameterByName("viewParameter1");

// Remove all values and tokens from the parameter value
myVP.parameterValue.clearTokens();
myVP.parameterValue.clearValues();

// Using the library, get the adapter based on it's name
var myTable = myLib.getAdapterByName("table1");

// One option is to set all the necessary properties of the new member
// An easy way to get this information is to use the developer console
// to expand the objects in of myVP.parameterValue.values
// after you've already chosen the desired member using a filter

// Below is an example of a member value from a flat hierarchy.
// Create a new MemberValue to push onto the values array.
var myMemberValue = new dundas.data.MemberValue({
    "hierarchyUniqueName": "Name",
    "levelUniqueName": "Name",
    "memberKind": "Regular",
    "uniqueName": "Cable Lock.Name"
});
// When the building a member value from a multilevel hierarchy, the uniqueName
// property of the member value will heavily depend on how the hierarchy was built

// Example: 5 level Address hierarchy = "Ontario.Toronto.D.Address"
// Example: 3 level Product hierarchy = "857.C.Products"
// 857 is the productId but what's displayed is "Men's Bib-Shorts, L"

// So understanding the hierarchy and the structure of the member is
// neccessary for building the member value correctly.

// Another option is to use the hierarchy service to get the desired member.
// Store the cellset from the tables metric set binding
var cellset = myTable.metricSetBindings[0].dataResult.cellset;

// get the hierarchy from the cellset based on it's unique name
var hierarchy = cellset.hierarchies.toEnumerable().first(function (hierarchy) {
    return hierarchy.uniqueName === "Products";
});

// Get the service
// We use the service instead of using this hierarchy since the 
// cellset in the table only includes what's needed to render
// so it could be an incomplete set of data
var hierarchyService = this.getService("HierarchyService");

// getMembers will return all the members from the specified hierarchy.
// analysisStructureId in this case is the origin cube id
var def = hierarchyService.getMembers(hierarchy.analysisStructureId, {
    // specify the unique name since there's likely more than 1 hierarchy in
    // the cube
    "hierarchyUniqueName": hierarchy.uniqueName,
    // specify the deepest hierarchy level unique name
    "levelUniqueName": hierarchy.levels[hierarchy.levels.length - 1].uniqueName
});

// In this example lets get all the members with "Bike" in the caption.
// I use caption since it's the test that's going to be displayed.
// the unique name could be an ID which wouldn't be helpful in this example.
def.done(function (members) {
    // loop through all the members
    members.forEach(function (member) {
        if (member.caption.indexOf("Bike") > -1) {
            // if the member has "Bike" in the caption,
            // load it into the values of the view parameter
            myVP.parameterValue.values.push(member.loadMemberValue());
        }
    });

    // Sets the value of lastModifiedTime to now
    myVP.invalidateParameterValueLastModifiedTime();

    // Update all the connected adapters with the newly modified values
    // Includes data visualizations and filter controls
    myVP.refreshAllAdapters();
});

5.5. SingleMember

// Using the library, get the view parameter based on it's name
var myVP = myLib.getViewParameterByName("viewParameter1");

// Remove all values and tokens from the parameter value
myVP.parameterValue.clearTokens();
myVP.parameterValue.clearValues();

// Time dimensions have a little bit more going on, so in this example 
// we will be pulling the member value from an existing metric set, 
// and just to make it interesting, we will use a data retrieval service
// to get the metric set data

// Metric set id from a precreated metric set
var metricSetId = "4f0ed0b9-3a4e-4517-a000-a21e593ca0c3";

// Get the Dundas DataRetrievalService
var dataRetrievalService = this.getService("DataRetrievalService");
var viewService = this.getService("ViewService");

// Create a request object using the metric set id
var request = new dundas.data.Request({
    "objectId": metricSetId,
    "requestData": dundas.Utility.createGuid(),
});

// Call getData from the service and store it in a def object
var def = dataRetrievalService.getData(request);

// Show the loading view
viewService.showLoadingRestCall(def);

// When the def is done run the following
def.done(function (dataResult) {
    // Load the member from the data result
    // grabbing the first row, and first member from that row
    // I've sorted the metric set to  always have the most recent 
    // date in the first row
    var myMemberValue = dataResult[0].cellset.rows[0].members[0].loadMemberValue();
   
    myVP.parameterValue.values = [myMemberValue];

    // Sets the value of lastModifiedTime to now
    myVP.invalidateParameterValueLastModifiedTime();

    // Update all the connected adapters with the newly modified values
    // Includes data visualizations and filter controls
    myVP.refreshAllAdapters();
});

5.6. RangeMember

// Using the library, get the view parameter based on it's name
var myVP = myLib.getViewParameterByName("viewParameter1");

// Remove all values and tokens from the parameter value
myVP.parameterValue.clearTokens();
myVP.parameterValue.clearValues();

// Similar to the SingleMember example the RangeMember uses an upper and lower set 
// of values, so in this example we will pulling members from same existing metric set, 
// and we will use a data retrieval service again

// Metric set id from a precreated metric set
var metricSetId = "4f0ed0b9-3a4e-4517-a000-a21e593ca0c3";

// Get the Dundas DataRetrievalService
var dataRetrievalService = this.getService("DataRetrievalService");
var viewService = this.getService("ViewService");

// Create a request object using the metric set id
var request = new dundas.data.Request({
    "objectId": metricSetId,
    "requestData": dundas.Utility.createGuid()
});

// Call getData from the service and store it in a deferred object
var def = dataRetrievalService.getData(request);

// Show the loading view
viewService.showLoadingRestCall(def);

// When the deferred object is done run the following
def.done(function (dataResult) {
    // Load the member from the data result
    // grabbing the first row, and first member from that row
    // and the 10th row (index 9) and the first member from that row
    // I've sorted the metric set to  always have the most recent 
    // date in the first row
    var myUpperMember = dataResult[0].cellset.rows[0].members[0].loadMemberValue();
    var myLowerMember = dataResult[0].cellset.rows[9].members[0].loadMemberValue();
    
    // Since this is a range member we place upper member into the upperBoundaryValue
    // and the lower member into the lowerBoundaryValue
    myVP.parameterValue.upperBoundaryValue = myUpperMember;
    myVP.parameterValue.lowerBoundaryValue = myLowerMember;

    // Sets the value of lastModifiedTime to now
    myVP.invalidateParameterValueLastModifiedTime();

    // Update all the connected adapters with the newly modified values
    // Includes data visualizations and filter controls
    myVP.refreshAllAdapters();
});

5.7. RangeDateTime

// Using the library, get the view parameter based on it's name
var myVP = myLib.getViewParameterByName("viewParameter1");

// Remove all values and tokens from the parameter value
myVP.parameterValue.clearTokens();
myVP.parameterValue.clearValues();

// A RangeDateTime parameter value will have an upper and lower value set
// similar to that of the RangeMember, but instead of member values inside 
// the upper and lower, there are just date objects

// Create a date time object for today
var currentDateTime = new Date(Date.now());

// Create a date time object for this time one year ago
var oneYearAgo = new Date(Date.now());
oneYearAgo.addYears(-1);

// Assign the dates to their respective upper and lower values
myVP.parameterValue.lowerBoundaryValue = oneYearAgo;
myVP.parameterValue.upperBoundaryValue = currentDateTime;

// Sets the value of lastModifiedTime to now
myVP.invalidateParameterValueLastModifiedTime();

// Update all the connected adapters with the newly modified values
// Includes data visualizations and filter controls
myVP.refreshAllAdapters();

5.8. TokenValue

// Using the library, get the view parameter based on it's name.
var myVP = myLib.getViewParameterByName("viewParameter1");

// Remove all values and tokens from the parameter value.
myVP.parameterValue.clearTokens();
myVP.parameterValue.clearValues();

// We are going to set the lower token to Open Range Boundary
// and the upper range to End of Current Year (-1).
// If you know the ID of the token you want to use, you don't need to
// use the service. You can simply pass a new object into the token
// constructor with the desired properties.
// The constants object has the common token ids.
myVP.parameterValue.lowerBoundaryToken = new dundas.data.ParameterToken({
    "id": dundas.constants.OPEN_RANGE_BOUNDARY_TOKEN_DEFINITION_ID,
    "caption": "Open Range Boundary"
});

// get the current view
var view = this.baseViewService.currentView;

// Get the token service
var tokenService = view.getService("TokenService");

// Get the correct CompatibleDataTypes.
var timeHierarchyDataType = dundas.data.CompatibleDataTypes.TIME_HIERARCHY;

// Get the desired TokenDisplayTypes.
var rangeEndTokenTypes = dundas.data.TokenDisplayTypes.DISPLAY_RANGE_END;

// Get the deferred object for the parameter tokens using the above variables.
var def = tokenService.getParameterTokens(timeHierarchyDataType, rangeEndTokenTypes);

// When the deferred object is done use the result to get the desired token(s).
def.done(function (tokens) {
    // Store the token to modify later.
    var endCurrentYearToken = tokens.toEnumerable().first(function (token) {
        return token.caption === "End of current year";
    });

    // Change the offset of the token.
    endCurrentYearToken.offset = -1;

    // Set the upper token to the new end of year token.
    myVP.parameterValue.upperBoundaryToken = endCurrentYearToken;

    // Sets the value of lastModifiedTime to now.
    myVP.invalidateParameterValueLastModifiedTime();

    // Update all the connected adapters with the newly modified values.
    // Includes data visualizations and filter controls.
    myVP.refreshAllAdapters();
});

6. Reset Parameter values to "All" or "Default"

All the filters on the dashboard can be reset to "All" or "Default" values via a script. The script works for all types of filters.

var baseViewService = this.getService("BaseViewService");
var view = baseViewService.currentView
return view.control.viewParameters.forEach(function(vp, index){
  if (index !== 0){ // skips the brushViewParameter
    vp.parameterValue.clearTokens();
    vp.parameterValue.clearValues();
    vp.parameterValue.token = new dundas.data.ParameterToken({
        //dundas.constants.ALL_TOKEN_DEFINITION_ID for "All" token
        "id": dundas.constants.DEFAULT_TOKEN_DEFINITION_ID,
        //"All" caption for All token
        "caption": "Default"
    });
    vp.invalidateParameterValueLastModifiedTime();
    vp.refreshAllAdapters();
  }
}); 

Dundas Data Visualization, Inc.
500-250 Ferrand Drive
Toronto, ON, Canada
M3C 3G8

North America: 1.800.463.1492
International: 1.416.467.5100

Dundas Support Hours: 7am-6pm, ET, Mon-Fri