Which files are overwritten during a Canvas upgrade

During a Canvas upgrade, the installer can upgrade either the Cubewise Application Server or the application folders (webapps) or both. That is why you have to be careful about which files you can and can't be changed to allow upgrades to work smoothly.

In this article we use the following color coding:

  • red: All files should not be updated.
  • yellow: some files can be updated.
  • blue: all files can be updated


  • backups: contains all application folders backups created during an upgrade.
  • conf: you can update the server.xml file to update the Canvas port number.
  • webapps: contains all Canvas applications.


    In the Conf folder the only file you should update is the server.xml file where you can update the Cubewise Application Server's port number. But do note that this will be overwritten if the option "Install Canvas Application Server" is selected. So migrate your settings after upgrade.

    In the Conf folder you will find the license file (Canvas.xml).



    In the webapps folder, the files inside samples folder are overwritten during an upgrade when the "samples" application is checked.



    An application folder

    • css: global format settings of the application.
    • html: all HTML pages.
    • images: all images.
    • js: all controllers.
    • menu: left pane menu structure.
    • WEB-INF: configuration.






    You can create as many HTML pages as you want. We recommend to use the Page Creator to create a new page.


    In the JS folder you will find all controllers, you can add as many controllers but just do not touch the admin and system folders.


    You can update manually the menu.json and the states.json file but you need to be aware that these files can be updated from the user menu management page in the admin section.


    • config: security settings such as updating admin password.
    • pages: index.ftl file, check the following article.
    • resources: Define all MDX queries.
    • instances.json: TM1 connection settings

    License file

    The Canvas application server will not work without a license file. To get a license file, you need to send the server name to your Cubewise local office. You need one license file per server.

    1. Once you have received the license file (Canvas.xml), put it in the CWAS\Conf:

    2. Then restart the Cubewise Application Server.

    3. Clear the cache (SHIFT + F5) and then refresh your browser, the "invalid license" message should have disappeared.

    If the message is still there, you can first check if the server name is correct in the license file. To see if the license has not expired, you can check the expiration date:

    Page break in PDF report

    When printing a report using Canvas, you can customize as much as you like the PDF output. There are lots of CSS properties that you can use such as CSS Media Queries to update for instance the background color of the PDF. The PDF can be very different from the HTML page.

    One thing to be careful about when you print your page is the page break. To avoid a table or a chart to be divided between two pages, you can define in your HTML page where you want the page break to appear.

    If you do not specify any page break in the HTML page when printing, your report can break anywhere:

    This article describes how the page break works in the sample print:

    • http://localhost:8080/samples/#/sample/print

    Create a CSS class

    At the top of the page, first you need to create a new CSS class. In the example below we create a new class called other-pages with the property page-break-before:always:

            page-break-before: always;

    page-break-before always insert a page break before an HTML element it is assigned to. There are other CSS properties that you can use such as page-break-after which insert a page break after an HTML element it is assigned to.

    Add the CSS class to an HTML element

    In the print example, we assigned the new CSS class to a div but you can add this class to any HTML element where you want the page break to happen:

    <div class="row other-pages"  >

    This div has now the CSS property to always break the page before, if you print the page you will see the page break just before the chart:

    To add a third page to your report you just need to add a new div with the other-pages property:

    <div class="row other-pages"  >
            Add a third page

    It is important to notice that the page break will appear only in the PDF, in the HTML page, it will be like a normal div:

    After printing you will see a new page:

    Override the default number format

    Canvas includes the accounting.js library. With accounting.js you can do advance formatting for number, money and currency.

    The default number format is:

    • Thousands separator: ","
    • Decimal separator: "."

    There are two ways to update the default format.

    1. Override the format for the all application

    The default number format is defined by applications. To update the default format for the all application, you need to update the client.startup.js:

    • C:\CWAS\webapps\<application name>\js\client.startup.js

    For example to show "." as thousands separator and "," as decimals, you will need to add the following lines:

        accounting.settings.currency.thousand = '.';
        accounting.settings.currency.decimal = ',';

    It is going to update the format for all numbers:

    2. Override the format for a specific DBR

    To override the format for a specific DBR, you need to add to the DBR the attribute tm1-accounting-settings-override. For example to show a "," as thousands, "." as decimal and a precision of 2, you need to add:

    • tm1-accounting-settings-override="{currency:{thousand:',',decimal:'.',precision:'2'}} "

    Save the file and refresh the page, now you should see the DBR with the new format:

    The attribute tm1-accounting-settings-override overrides the attribute tm1-data-decimal. For example if you have tm1-data-decimal="2" and  tm1-accounting-settings-override="{currency:{thousand:',',decimal:'.'}} " in the same tm1-ui-dbr:

    It will show a value with no decimal because the default precision of accounting.js is 0. To see a precision of 2 you need to add precision:'2' to tm1-accounting-settings-override:

    Index.ftl structure

    Canvas is a single page application SPA. Each Canvas application has a single web page which swaps and loads its different contents, depending on what the user click. All HTML pages are loaded in the container (blue). A single page (red) is loaded, that is why you see a “#” between the URL and the HTML path:

    The red area is defined by the index.ftl file and the blue area is your HTML page. The index.ftl file is used to update everything that you find in the red area such as logo, headers, menu and homepage.

    Prior v1.2, to update the logo or add a custom library you had to update the index.ftl in the following folder:

    • C:\CWAS\webapps\<application name>\WEB-INF\pages

    We moved the index.ftl to the following new folder:

    • C:\CWAS\webapps\< application name>\WEB-INF\pages\system

    So updating you logo is now done through the navigation.logo.ftl file.

    Important: If you upgrade your existing Canvas application to Canvas v1.2. You will have to migrate all changes you made from your index.ftl (WEB-INF\pages\) into the different new ftl files (WEB-INF\pages\). The index.ftl file which is used by the Canvas application is in \WEB-INF\pages\system.

    We did this in order to split the index.ftl file between the area you can update and the area you should not update. Starting with v1.2, the WEB-INF\pages\system\index.ftl file should not be updated anymore. The area you can update is now separated into different files that you can find in \WEB-INF\pages. The new index.ftl will include these new customizable ftl file during application load.

    There are now 9 ftl files:

    • header.library.ftl: To add links to your custom libraries.
    •  header.script.init.ftl: For configuring your SSO and adding your angular modules.
    • header.script.others.ftl: Configure your accounting.js settings and other initializations.
    •  navigation.body.custom.ftl: Make your own navigation body.
    • navigation.logo.ftl: Update the logo.
    • navigation.top.left.ftl: For adding items into the top left navigation bar.
    •  navigation.top.right.ftl: For adding items into the top right navigation bar.
    • page.footer.ftl: Add your custom page footer.
    • page.header.ftl: Add your custom page header.

    The contents of these files get inserted into the index.ftl file when your Canvas application loads. Should you want to know more about the expected content of each FTL file, you can check out the index.ftl file to see where these files will be inserted and what HTML elements are near it.

    Schedule jobs to send PDF reports

    Starting with Canvas v1.2, you can now print your Canvas page into a PDF report and schedule a job to send it by email at a specific day or time. This article describes the steps how to create a job scheduler.

    Set up SMTP configuration

    Canvas allows you to send email alerts, to do this it needs to access an SMTP server. For most corporate networks the SMTP server will accept any email send requests from servers in the same network.

    To update the SMTP configuration go to the setings page in the Admin section, you can find below the settings of an office 365 account:

    For more information about SMTP configurations, you can check the following Help article: Email settings.

    Go to Reports Manager

    To create a job, you have to open Reports Manager.

    • http://localhost:8080/<application name>/admin#/reports-manager

    You will see first the job list, click the + button to create a new job:

    Create a new Job

    First you need to enter the Job details such as Name, Subset, Recipients and the Email Body:

    To add more recipients, just separate their email addresses with ",":

    Schedule the job

    Click on the icon to pop up the Scheduler Helper. There are different options to choose from for scheduling your job such as every month, week, day, etc.:

    Click the Check Schedule button to see the next runs. Finally click Apply Schedule.

    Do not forget to add the name, the name will be shown in the job list.


    Attachments are the URL path to the Canvas pages, Canvas uses the URL to create PDF reports. If you want to send the report with the filter England, you have to make sure that the filter is in the URL, if not it will always print the report with the default filters. To learn how to dynamically update the URL, you can check the following help article : Update the URL before printing.

    Do not forget to add the credentials to login to the TM1 instances (instance name, user name and Password).

    Click the save button to make sure your new job is set up correctly. You can test your job by clicking Execute button:

    If you go back to the job list, you should now see your new job:

    Update the URL before printing a page

    With Canvas v1.2, you can now print and schedule a report. Canvas uses the page URL to print a report in PDF. If you do not update the URL, Canvas will always print the report with the default criteria.

    This article explains how you can update the URL without reloading the page.

    In the "print" dashboard, if you click on one of the KPI at the top, for instance Gross Margin, the URL will be updated:

    The print button in Canvas, uses the current URL to create the PDF report.

    If the URL is not updated, when you click on the print button, Canvas will print the default URL:

    • http://localhost:8080/samples/#/sample/print

    instead of printing the report with Gross Margin:

    • http://localhost:8080/samples/#/sample/print?driver=Gross%20Margin

    To modify the URL without reloading the page, we are going to add a new function in the controller (JS page) and from the HTML page, we are going to call this function.

    1. Create the function in the controller

    $location.search definition

    To update the URL, we are using the search method of the angular service $location. The $location service parses the URL in the browser address bar and makes the URL available to your application.

    How does it work:

    1. $location makes the URL available to our application
    2. We use search method to update the URL.

    Add $location as a new controller argument

    To be able to use $location service in our controller we have to add it as a new argument in our controller:

    Declare variables

    We need two variables:

    • $scope.defaults.driver: default values to be used before selections are made
    • $scope.page.driver: value which will be updated during navigation

    In the example below we have three defaults variables (defaults.region, defaults.department and defaults.driver) and 6 variables that we are going to use in our HTML page (page.region, page.departement, page.version, page.driver, page.segment and page.subset):

    Get a value from the URL

    To get a value from the URL we use the search method: $location.search()

    In our example we want to get the driver value so we attach driver to $location.search():

    • $location.search().driver

    If the URL is http://localhost:8080/samples/#/sample/print?driver=Operating%20Expenses then $location.search().driver will be equal to Operating Expenses.

    Initialize the page variable

    If there is a driver value in the URL we initialize the page.driver variable:

            $scope.page.driver = $location.search().driver;

    Send a value to the URL:

    We're going to create a new function called setDriver which will be called from the HTML page. The objective of this function is to update the URL if the driver in the page (scope.page.driver) is different from the default driver (defaults.driver):

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

    2. Update the HTML page

    In the HTML page, we just need to call the setDriver function created in the controller when we click on a button:

    • ng-click="setDriver(item.description)"

    In this example when we click, we send the item.description to the URL.

    Create a new page using Page Creator

    To create a new page, it is recommended to use the Page Creator which you can find in the Admin section. Each Canvas application has its own Admin section. In the following example, our application name is training. You can access the Admin section of the training application via the following URL:

    The default log in is ‘admin’ and leave the password blank, then click the Login button:

    If you forgot the admin password, you can reset it by following these steps.

    You can access the Page Creator via the left pane menu, then click Blank Canvas Page:

    • Page Name: Visualisation
    • Menu Name: Visualisation
    • Menu Icon: fa-bar-chart

    Click the Create button and then go back to the training application:

    Refresh the page (or press F5) and you should be able to see the new page, Visualisation:

    When you click the create button, Canvas will create an HTML page with just the icon and the title defined.

    When you use the Page Creator to create a new page, Canvas creates a new HTML file with the same name in the <application name>\html folder. Canvas generates a basic HTML code, the header with the title and icons you chose (in orange) and an empty row with 3 blocs (in yellow), just to pre-define the structure of the page.

    Note that Canvas will also create a controller (JS file) in the controller folder (js/controllers).

    Query an external database from Canvas

    With Canvas you can display data coming from your TM1 server and also from an external database. An example can be found in the samples:

    • http://localhost:8080/samples/#/sample/sql

    Define ODBC Connection

    For Canvas to access the datasource, you have to first set up the ODBC Connection. Note that if the samples application has been selected during installation, a corresponding ODBC connection should come pre-configured and will be shown as below:

    Define the SQL query

    The SQL query and configuration are created on the server so you only have to pass through parameters from JavaScript. It also adds an important layer of security, it is generally a bad practice to allow SQL or MDX to be created/modified in a user interface as it allows users or third parties the ability to change what is executed. This could include changing a SELECT statement to an INSERT, UPDATE or even a DELETE command.

    To create a new query, you can create a new file based on the <application name>/api/samples/sql.jsp and then replace the SQL settings:

    • In red, this is where you define the connection to the database.
    • In blue, the SQL query.
    • In black, the parameters, one for each “?” in the query.

      query.setString(1, department); represents the first “?” in the SQL query.

    Initialize the data in the controller

    Once the SQL query is set up in the jsp file, the next step is to call the query from the controller and store the result of the query into the $scope.data variable ($scope.data = result.data):

    $scope.query = function() {
            $http.get("api/samples/sql.jsp?instance=dev&department=" + $scope.page.department + "&skip=0&max=" + $scope.page.max).then(function(result){
                $scope.data = result.data;

    If you are using a new query stored in a new file called newsql.jsp, access your SQL query by sending a GET request to the following path: api/samples/newsql.jsp.

    Call the query from HTML page

    Once the $scope.data is defined in the controller, in the HTML page you can display the result of the query by using data variable:

    <tr ng-repeat="item in data">
            <td>{{item.Amount | number}}</td>

    Change the default colors of a chart

    There are 3 different ways to update charts colors in Canvas:

    •      Update the default application color scheme.
    •      Define the color scheme in the chart property.
    •      Define the color of a specific chart element.

    Update the default application colour scheme

    In Canvas, when you create a chart, if you do not specify any colors, the chart will take the default application colors. These default colors are defined in the instances.json file in the WEB-INF folder of your application:

    Colours are defined in CSS colour format. You can find lots of colour supported by all browser in w3schools website:

    You can get more colours by clicking on the Shades button:

    Let’s update the instances.json file with the following colours:

     "chartColorScheme"=["#0000ff", "#3333ff", "#6666ff", "#9999ff", "#b3b3ff"]

    For Canvas to pick up the changes in the instances.json file, you have to restart the Cubewise Application Server. Then refresh your page and you should see the new colours:

     Define the colour scheme in the chart property.

    You can override the application default scheme by adding the tm1-color-scheme attribute to the tm1-ui-chart:

    tm1-color-scheme='["#009900", "#00b300", "#00cc00", "#00e600", "#00ff00"]':

    Save the page and refresh your web browser, you should now see new colours:

    Define the colour of a specific chart element

    You can override the chart colour scheme for a specific bar by adding the tm1-color attribute to the tm1-ui-chart-dbr:

     tm1-color ="#000000”

    Let’s add this attribute to the first bar:

    Save and refresh your page, you should now see the first bar with a black colour:

    Debug a Canvas page (Controllers and Debugger)

    Each browser has each of its own debugging tools to help you troubleshoot your web application. And each tool gives you different views and helpful information about your HTML page. 
    On this article, we will be using Chrome as the browser and how we can debug by enabling breakpoints.

    To debug a web page, there are 2 steps that you will need to do beforehand. First you need to mark a stop in your code where you want the browser to stop when its refreshing the page. Then, once the browser stopped, you can start debugging by going through your code step by step.

    Set up the debug point

    Inside the JavaScript codes

    Note that the Developer Console (press F12) must be open before proceeding. Here are the two common ways that you can do to enter debugging mode:

    var i = 0;
    // other logics here...
    debugger; // pause here

    Adding this line of code into your JavaScript will tell Chrome to halt execution up to this point. 

    Inside the browser:

    A second way is: on the Sources tab, navigate to the JS file that you wanted to debug. The contents of this file will be shown on the right which should also show the line numbers for each code. Clicking on the line number for which you want to halt execution will enable/disable breakpoint.

    Start debugging

    Now that you have setup your debug points, it is time to start examining!
    Let us say, we have a page debug.html, with the following SUBNM where we would like to do something when the value of the SUBNM changes (tm1-change="page.onSubNmChange(page.year)"):


    and a controller debug.js with the following code:

    $scope.page = {};
    $scope.page.onSubNmChange = function(data){
      for(var i = 1; i < 10; i++){
        console.debug('i: %o', i);  
      console.debug('onSubNmChange %o', data);

    As you can see, there is a line of code containing 'debugger;'. Once you reload the page, your console should look like this:

    Notice the debugger was highlighted in blue. We are now in debug mode!

    On debug mode, there a few more buttons now available that can help you. Hovering the mouse pointer over them will give you the keyboard shortcuts to trigger them.

    For simplicity purposes, we will just focus on two functions: F8 and F10. You will see these on the main browser screen too.

    Pressing F8 means it will continue on until the next breakpoint or debugger; line. Whereas pressing F10 means, "execute this line of code, and go to the next".  Since we are in debug mode already, do explore the Sources tab and hover over some variables. Think of this as a way of examining processed variables at certain point of execution! And this is how it can look like as you hover (I hovered over the variable i, to see what is the current value):

    Pressing F10 and examining the variables along the way will give you an idea on what and how it is currently working. This should also help you trace through your various functions, especially if you are calling a function within a function!

    Create a table from a MDX statements

    MDX is a powerful query language similar in structure of standard SQL. Where it differs is it ability to deal with multidimensional data as opposed to the flat structure of a table in a relational database.

    Canvas has many helpful components that enable you to avoid the complexity of writing MDX statements but if you want to dive deeper into the internals of TM1 you can still do this via Named MDX statements.

    Named MDX statements are created on the server so you only have to pass through parameters from JavaScript. It also adds an important layer of security, it is generally bad practice to allow SQL or MDX to be created/modified in a user interface as it allows users or third parties the ability to change what is executed. This could include changing a SELECT statement to an UPDATE or DELETE command.

    Named MDX statement structure

    Named MDX statements are stored in a JSON file on your Canvas server. The file is located at:

    • <Canvas Install Location>\<Application>\WEB-INF\resources\mdx_named.json
    • Example: C:\CWAS\webapps\ROOT\WEB-INF\resources\mdx_named.json

    The file contains an array of named mdx statements in JSON format:

        "id": "P&L",
        "mdx": [
          "SELECT NON EMPTY {[Period].[Oct], [Period].[Oct YTD], [Period].[Year]} * {[Version].[Actual], [Version].[Budget]} ON COLUMNS,",
          "NON EMPTY {[Account].AllMembers} * {[Department].AllMembers} ON ROWS",
          "FROM [General Ledger]",
          "WHERE ([Year].&[{{Year}}], [Region].&[{{Region}}], [General Ledger Measure].&[Amount], [Currency].&[Local])" 
        "mdxParams": [
            { "name":"Year", "value":"2012" },
            { "name":"Region", "value":"3", "escaped": true }

    The file has the following properties:

    • id (string): This is a unique id used to identify the statement you want to execute.
    • mdx (array of strings): This is the MDX statement itself, instead of a single string it is an array of strings to make it more readable. Note the use of [ ] square brackets around each of the strings.
    • mdxParams (array of parameters):
      • name (string): The name of the parameter used in the MDX statement. In the MDX statement the parameter should be used like this {{ParameterName}}.
      • value (string): The default value of the parameter, if the parameter is not passed to when executing the MDX the default value will be used.
      • escaped (optional boolean): Whether to escape the any closing square brackets ( ] ) in the parameter values. The default value is true.

    include NAMED MDX STATEMENT in a HTML page

    The easiest way to show data  from a MDX statement into a Canvas page is to use the Canvas directive tm1-ui-table-mdx:

       tm1-instance="Instance Name"
       tm1-cube="Cube Name"
       tm1-mdx-id="MDX ID"

    tm1-ui-table-mdx is going to manage how the data will be displayed depending on the MDX statement. If two dimensions are on rows, the directive will merge the cells to avoid elements to be replicated many times. 

    An example of the tm1-ui-table-mdx can be found in Canvas components called MDX Table:


    Let's build a new tm1-ui-table-mdx using the P&L MDX statement already written in mdx_named.json.

    In a new page, add the following HTML code:

       tm1-cube="General Ledger"

    If you save your HTML file and refresh the Canvas page, you should see the table as below:

    Use tm1-dimension-attribute to show dimensions alias

    To show alias instead of the elements id for dimensions on rows and columns, we need to add the parameter tm1-dimension-attribute="{<dimension name>:<attribute name>"}:

       tm1-cube="General Ledger"
       tm1-dimension-attribute="{Account:'Description', Department:'Description', Period: 'Short Description', Version: 'Description'}"

    Save and refresh the page, you should see now the aliases on rows and dimensions:

    Dynamic MDX statement

    Currently the structure of our MDX statement is static, one way to show data from a different year is to go to the mdx_named.json file and update the MDX statement. The P&L MDX statement has 2 parameters Year and Region. Let's replace 2012 with 2011:

    Save the mdx-named.json and refresh the Canvas page, you should see now 2011 values:

    Another way to update these parameters is to add tm1-mdx-parameters="{Parameter Name:Parameter Value}" to the tm1-ui-table-mdx. Using the tm1-mdx-parameters will enable you to pass the parameters value from the HTML page to the JSON file where the MDX query is defined:

       tm1-cube="General Ledger"
       tm1-dimension-attribute="{Account:'Description', Department:'Description', Period: 'Short Description', Version: 'Description'}"
       tm1-mdx-parameters="{Year:'2011', Region:'England'}">

    Customize the tm1-ui-table-mdx

    To customize the look of the tm1-ui-table-mdx such as removing the pagination, you'll need to update the code behind the tm1-ui-table-mdx. You can find an example in the samples called Named MDX:

    You can copy the HTML code behind this table and start customizing the table. For instance to remove the pagination, you'll need to delete the red part below:

    Manage multiple screen sizes with matchMedia

    Canvas includes the matchMedia library. This Angular library helps you to check which screen size is your page displaying and returns true if the current screen width matches what you need or false if not.

    You can use this angular service to show or hide columns depending on the screen size:

    • xs: Extra small < 576px
    • sm: Small ≥ 576 px
    • md: Medium ≥ 768px
    • lg: large ≥ 992px
    • xl: Extra large ≥ 1200px

    For example, let's say that we have the following table with LY, Year and the 12 months on columns:

    On a small screen you do not want to show all months, you just want to show LY and Year.

    In order to do that you will need to update the controller and then the HTML file.

    Update the controller

    In the controller you will need to enable the library by adding screenSize as one of the dependencies. You can do this by updating the top part of your script / controller as done below:

    app.controller('DataEntryCtrl', ['$scope', '$rootScope', '$tm1UiTable', 'screenSize', function($scope, $rootScope, $tm1UiTable, screenSize) {

    and then, to make it available for use on your HTML page too, create and assign a screenSize property into your $scope and assigned the 'screenSize' library into this variable:

    $scope.screenSize = screenSize;

    The controller will look like this:

    Update the HTML file

    In the html table you will need to use ng-if to show the months columns only if the size is medium (md) or large (lg). To do this, just add the ng-if="screenSize.is('md, lg')" inside the table header:

    <th ng-if="screenSize.is('md, lg')" 
        ng-repeat="month in page.months">{{month}}</th>

    and inside the table data:

    <td ng-if="screenSize.is('md, lg')" 
        ng-repeat="month in page.months" class="text-right" >

    More information about matchMedia can be found into its GitHub page.

    An example of matchMedia can be found in the training session8 (Remove columns chapter):

    Upload files and images

    Aside from the reading and writing back numbers and strings into TM1, Canvas further extends TM1 functionality by allowing you to save URL paths that you can then use to display images for example, or embed link and control access to these links - the TM1 way.

    To start uploading files, it is as simple as writing the following:

    <tm1-ui-upload tm1-instance="dev"></tm1-ui-upload>

    This will give you the following:

    Clicking on the "Select File" on your page will open up a dialog box which will ask you for a file to open/upload. And that is it!

    Now, where did the file go?

    Let us create a full example to better explain what is going on by re-writing the previous example so that we can:

    1. Get the URL path
    2. Save this URL path into TM1
    3. Display an image wherever applicable

    This is the HTML mark up now of our code:

    <tm1-ui-upload tm1-instance="dev" 
    <tm1-ui-dbr-image tm1-instance="dev" 
                      tm1-cube="System Info" 
                      tm1-elements="Current Date, Comment"></tm1-ui-dbr-image>

    And this is the corresponding function updatePreview, on our controller file:

    $scope.updatePreview = function(file){
            // uncomment to see what is being returned
            // console.debug(file); // instance, name, path
            $tm1Ui.cellPut(file.path, 'dev', 'System Info', 'Current Date', 'Comment').then(function(data){
                // uncomment to see what is being returned
                // console.debug('data %o', data);

    Below is the sequence of events:

    1. The tm1-after-upload is an attribute by tm1-ui-upload directive that allows you to specify a function to be called after it has finished the upload.
    2. Within the function, we then use a simplified script in saving data into TM1.
    3. The directive tm1-ui-dbr-image is a variation of DBR that allows you to show images from a properly formatted URL in TM1.

    The files are uploaded, relative to your Canvas application, within files/<instance> folder by default. If you want to save it into a different folder instead, go into your Canvas' Admin console --> Settings and update the following:

    Hide the context buttons

    In Canvas, when you click on a cell which contains a tm1-ui-dbr, the context button will appear. Once you click on this button you'll see a dropdown list with the following options.

    • Reference: Get the TM1 cell reference
    • Spread: Do a spreading
    • Drill: If a drill is set up in TM1, you'll be able to access it.
    • Comment: Input comments using cell annotation or comment measures

    If you want to hide the context button, you need to set to false the 4 following attributes to the tm1-ui-dbr:

    • tm1-hide-reference: hides the Reference
    • tm1-hide-comment: hides the comment
    • tm1-hide-spread: hides the Spread
    • tm1-hide-drill: hides the drill
    • tm1-hide-context-menu: disable the context button

    Different types of DBR

    Similar to TM1 and Excel, Canvas has adopted a cell based approach to application design.  This means each cell in Canvas has its own DBR formula to retrieve and to update TM1. 

    There are 4 different types of DBR:


    A DBR-like implementation for retrieving cube data from TM1. You need to use this directive to build a data entry template. This is the only directive with the write back feature.


    A DBR-like implementation for retrieving cube data from TM1 that is hidden and to be used with ng-model to retrieve cube values. For example, if you need a value to suppress zero, you can use this directive to get a value which will not be displayed in your page. The advantage of using tm1-ui-dbr-hidden instead of tm1-ui-dbr is that if there is a picklist in the cell, tm1-ui-dbr-hidden will retrieve only the value instead of the all picklist.


    A DBR-like implementation for retrieving cube data from TM1 that is always read-only and to be used with ng-model to retrieve cube values.

    tm1-ui-dbr-read-only has been created in order to make your Canvas page even faster. For example, it will not retrieve any picklist values as compared to the tm1-ui-dbr which retrieves not just the values, but also the whole picklist options.

    When you build a dashboard where you do not need to input data, it is recommended to use tm1-ui-dbr-read-only.

    Using tm1-ui-dbr with the attribute tm1-read-only=”true” or  tm1-ui-dbr-read-only will display the same thing on your Canvas page but the difference is that  tm1-ui-dbr-read-only is much faster.

    tm1-ui-dbr vs tm1-ui-dbr-hidden and tm1-ui-dbr-read-only

    Some tm1-ui-dbr functionalities have been removed and recreated into tm1-ui-dbr-hidden and tm1-ui-dbr-read-only. These 2 directives are much lighter and make the rendering of an HTML page faster:



    A DBR-like implementation for retrieving cube data containing paths to images uploaded via tm1-ui-upload from TM1.

    Drillthrough in Canvas

    Since TM1 10.2.2 FP6, the drill through has been added to the TM1 REST API. You don't need to do anything on the Canvas side to enable the drill. If the drill is set up in TM1, it will appear as an option in the context button. An example of drill through is available in the Full Dashboard example: 

    Once you click drill, you'll see the cube view which is defined in the TM1 drill process. In the example below there are 2 drill processes, one called "Source Table" and the other one called "Transactions":

    If you drill the same cell in TM1:

    You'll see that in TM1 you'll have access to the same drills:

    Include HTML contents inside your Canvas page

    When you have lots of HTML components, your HTML page can easily contain hundreds of lines of codes. The more HTML components you add in your HTML page, the harder it will be to find information or to understand how it has been built.

    Instead of creating all the HTML components in a single HTML file, you can split the components into different files and then use the Angular's ng-include directive to include them back into the main HTML page. 

    The advantages of this method are that it enables you to easily reuse HTML components in your other pages and also to better organize your HTML page so it will be easier to read and to understand how it has been built.

    Organize your HTML page by block

    In the Visualisations sample, there is an example of ng-include:

    In the main HTML page (html/samples/sample-advance-chart.html), the Chart Type 1 and Chart Type 2 HTML codes are in 2 separate HTML files. They are including in the main page using the  ng-include directive:

    <div class="row">
        <div class="col-md-6" ng-include="page.pageLeftlocation">  </div>    
        <div class="col-md-6" ng-include="page.pageRightlocation"> </div>

    In this sample the name of the pages "pageLeftLocation" and "pageRightLocation" are defined in the associated JS file js/controllers/sample/sample-advance-chart.js:

    You do not have to store the variable name in the JS file. You can alternatively set up the full path to the HTML file as a String value of the ng-include.

    For example, let's replace the Chart Type 1 block by the SUBNM component page:

    <div class="row">
        <div class="col-md-6" ng-include="'html/samples/components/subnm.html'"> </div>
        <div class="col-md-6" ng-include="page.pageRightlocation"> </div>

    Save the HTML changes and refresh the Visualisations page. You will see now the SUBNM page as part of the Visualisations sample:

    Parameters flow through the sub-pages

    Parameters which are defined in the main page can be used in the sub-pages. If you change the value in the main page for example the Region, you will see that the charts which are in different pages are updated as well.

    Trigger an action from a chart

    With Canvas you can customize the chart behavior, for example you can trigger an action when clicking on a bar chart.
    An example has been setup in the Visualisations sample page showcasing how you can modify the options, and, for this example, be able to grab the data attached to the bar element that was clicked on by the user on the front end.  A table is then displayed corresponding to the month of the bar element:

    How does it work?

    A new attribute has been added into chart, tm1-options-override (you can see an example in sample-advance-chart.left.html):

    Details of the object that was added on the HTML is in the page’s corresponding controller (sample-advance-chart.js):

    For our example, this is defined in the JavaScript file attached to the Visualisations sample: js/controllers/samples/componenets/sample-advance-chart.js.
    The part of code where you can define which action you want to trigger (once user click on the bar chart) is the section starting with elementClick:function(e){:. Other options that you can configure into this can be found on Angular NVD3 site.

    Now, lets first un-comment the code in order to see what is being passed:

    When you click on the bar chart, you will see a window pop-up with the details of what is inside the variable e:

    Note that opening up the browser Console (usually by pressing F12) will show also the full data stored on variable e due to the action of this line: console.debug(e);

    In our example we want to get the month (third element in this list). So in order to get the 3rd element, we conveniently converted the elements String into an Array, and then retrieve the 3rd item on this array. As a shortcut, it was written as e.data.elements.split(',')[2]. This will return what we wanted and we stored the result in a variable called “barMonth”:

    $scope.page.barMonth = e.data.elements.split(',')[2];

    Now in the HTML page, we will then use the variable and pass it on as one of the parameters on our DBRs there. We can simply use it as {{page.barMonth}} and use as per normal.

         tm1-elements="{{page.Version}},{{page.Year}},{{page.barMonth}},{{page.Currency}},{{region.key}},Mountain Bikes,Sales Amount" 

    Create a simple table

    The objective is to create the following table, one column with the departments and the second will be Actual values:

    HTML Table definition

    HTML tag for a table:

    Tables in HTML are defined between <table> and </table> tag. Tables are divided into table rows by <tr> and </tr>. Then table rows are divided into table headings: <th>, or table data: <td>.

    Table Structure in HTML:

                 <th>Table Header</th>
                 <td> Table Rows</td>

    Create a TABLE

    1. Create a row set List

    First we need to create a set of elements which will drive the row set table. tm1-ui-element-list directive will create an element for each member of a subset and save the list to the page.depts variable:

    <tm1-ui-element-list tm1-instance="dev" 

    2. Create the Table header

    The table will have only 2 columns Departments and Actual:


    3. Create the Table Body

    ng-repeat will create one row per each element in the list populated by tm1-ui-element-list.

    <tr ng-repeat="dept in page.depts"> means that it will create one variable "dept" per each element in "depts".

    In the first column (<td>{{dept.Description}}</td>) it will show the Description attribute of the variable dept. The second column will be a dbr to get the data. In the tm1-ui-dbr we pass a parameter {{dept.Description}}, on each row the dbr will be linked to the current department.

          <tr ng-repeat="dept in page.depts">
            <td><tm1-ui-dbr tm1-instance="dev"
                          tm1-cube="General Ledger"
                          tm1-elements="Actual,2012,Year,Local,Total Europe,{{dept.Description}},Net Income,Amount"

    Almost there, now if you see your table in Canvas, it will look like a simple table:

    4. Add a bootstrap class

    Now if you want to make your table look nicer, you can use one of the bootstrap table class to give your table a modern look and feel.

    For example if we use :

      <table class="table table-bordered">

    or if you use class="table table-striped" it will look like: