Synchronizing SUBNM and URL

This article describes how to make the SUBNM component to sync with the URL whenever it changes. This will also describe how the SUBNM's initialization works.

The problem

Let's take the following page which has one SUBNM, every time the SUBNM is updated, the URL is updated as well.

One common issue that you might have, is when you print the report in PDF, instead of showing the current value (England), the value in the SUBNM always shows the default value (Total Europe).

To understand why, when you refresh the page or when you print the page, the value displayed in the SUBNM is always the default value, we will go through the code of the HTML page.

Define the default value

In the controller there are two variables:

  • defaults.region: the default value is set to 1 (Total Europe).
  • selections.region: The variable which is going to be updated from the SUBNM.
    $scope.defaults = {
        region: '1'
    };

    $scope.selections = {
        region: $scope.defaults.region
    };

SUBNM

In the HTML page, we have a basic SUBNM driven by the Default subset of the Region dimension.

<tm1-ui-subnm
    tm1-instance="dev"
    tm1-dimension="Region"
    tm1-subset="Default"
    tm1-default-element="{{selections.region}}"
    ng-model="selections.region"
    tm1-change="setRegion(data)"
>
</tm1-ui-subnm>
  • tm1-default-element enables us to set the default value of the SUBNM to the selections.region.
  • ng-model is used to store the value chosen by the SUBNM in the variable selections.region.
  • tm1-change is used to trigger an action each time the SUBNM value is updated. Every time the value of the SUBNM is updated, the function setRegion is triggered.

The function setRegion is defined in the controller. This function updates the selections.region variable and update the URL:

$scope.setRegion = function(region){
  $scope.selections.region = region;
  if(region != $scope.defaults.region){
    // Set the URL parameter
    $location.search("region", region);
     }
   else {
     // If the parameter equals the default value remove it from the URL
     $location.search("region", null);
      }
 };

We use location.search() to get the value from the URL. If there is a value in the URL, when you refresh the page, the selections.region will be set to this value:

if($location.search().region){
        $scope.selections.region = $location.search().region;
    }

SUBNM Deep Dive:

When you refresh the page, the SUBNM initializes following these two steps:

Step 1: The SUBNM retrieves the elements from the subset.

Step 2: It initializes the ng-model (ng-model="selections.region"). It means that it initializes the selections.region variable with the first element in the subset (Total Europe).

Even if the selections.region value was defined in the controller, this value is overwritten by the SUBNM.

Step 3: The SUBNM checks the value defined in tm1-default-element attribute, selections.region. At this stage the selections.region is currently equal to Total Europe.

Each time you refresh the page the selections.region variable is set back to Total Europe (the first element in the subset).

That is why the variable used for the tm1-default-element and the ng-model has to be different.

The solution:

To do that, replace the selections.region with a new variable values.urlRegion:

  • tm1-default-element="{{values.urlRegion}}"

<tm1-ui-subnm
     tm1-instance="dev"
     tm1-dimension="Region"
     tm1-subset="Default"
     tm1-default-element="{{values.urlRegion}}"
     ng-model="selections.region"
     tm1-change="setRegion(data)"
>
</tm1-ui-subnm>  

This new variable will be used only to update the URL and set the SUBNM default value.

In the controller, the URL is now driven by this new variable values.urlRegion:

    $scope.values = {
        urlRegion: $scope.defaults.region,
    };
    
    if($location.search().region){
        $scope.values.urlRegion = $location.search().region;
    }
    
    $scope.setRegion = function(region){
        $scope.values.urlRegion = region;
        if(region != $scope.defaults.region){
            // Set the URL parameter
            $location.search("region", region);
        }
        else {
            // If the parameter equals the default value remove it from the URL
            $location.search("region", null);
        }
    };

Now when you print the report or if you refresh the page, the SUBNM value will match the URL value: