Routing in Canvas

Hi there,

How do I do routing in Canvas? Let say I would like to do something like:

http://localhost:8080/#/PnL/CompanyB where PnL is a dashboard built on Canvas, and we would like to pass CompanyB as the element name, so that PnL will display data from CompanyB only.

I think this should be quite a common request, just wondering what’s the best practice of doing that in Canvas.

Thanks

Tat

Hi @twong,

Check out the Printing sample. It should be able to help you out on what you wanted to achieve here.


Paul

Hi Tat,

The Navigation sample shows how to do routing, the Printing example will show you how to use URL parameters. Either will work in a similar way, URL parameters are more flexible but the routing option looks cleaner.

Thanks Paul and Tim, I think the URL parameter probably works better for me as I may need to pass multiple parameter and if I can seperated with a “&” sign, it looks more nature to users comparing to routing.

Will give it a try and let you know if I hit any problem.

Thanks

Hi Tat,

There is a new article in the Help section which describes how to update the URL before printing a page:

Cheers,

Hi Guys,

How would one pass in a filter json object to your url and not just a single variable value?

As an example:

  1. services run that retrieve data from tm1 and store the data as objects
  2. User clicks one filter button, which causes a function to trigger that switches out the objects linked to graphs

At point 2, i would like to update the URL parameters in order to print what the user is currently seeing.

Thanks in advance!

Hi @gpool,

Although you can always convert the JSON to its string representation (i.e. via angular.jsonTo() function), this may not be a good practice to begin with. For one, URLs normally has a 2000 character limit. Then checking that by itself can become very complicated if it is off by one character, etc.

Regarding item#2, if you need to retrieve it from TM1 or from data sources, you can always just store the ID of the object itself in the URL parameter and retrieve that when the page loads. If the directive that you are using does not support dynamic parameters, you can always put all of it within a DIV and utilize an ng-if to re-initialize it.

With this, you could always just retrieve the data and if the directive that you are using has a watcher on it - chances are, you do not need to do something on the HTML side. You just need to ensure that you have captured the changes and the URL and update your object that you feed into the directive correctly.


Paul

Hi @gpool,

How complex is the object? There are a few libraries that can convert an object to name/value pairs, i.e.: jQuery.param() | jQuery API Documentation and GitHub - sindresorhus/query-string: Parse and stringify URL query strings

If if isn’t too big you could use one of those.

Hi @tryan,
It is nested objects.
Thanks for those are quite handy libraries - Im leaning towards @plims suggestion though, but I will try them out also and see.

Hi @plim,
I see your point in par1.
I will test out your suggestion in par2 above - may lose some performance, but overall should be the simplest approach/most troubleshoot friendly.

I will let you guys know how it goes.

Thanks for the help!

Hi @plim,

I went for the option of “…put all of it within a DIV and utilize ng-if to re-initialize it”

I’m still making a mistake somewhere/misunderstanding a step though.
With this step you do not have to adjust your URL?

To be honest, I dont understand exactly how phantomjs picks it up from here in the backend?
Does it rebuild the page behind the scenes, injecting variables specified in the URL?

I added this div wrapper:
image

Current Flow and result:

  1. When the page loads for the first time, the ‘showALL’ scope variable is set to true.
  2. All JSON objects built and populated from TM1…once this is done, the UI is updated. (graph rendering/values etc)
  3. User clicks on division button = modal pops up = user selects a division
  4. When he selects a division, broadcast is fired to the the controller scope and this code runs (extract):
    image

$scope.totalBars and $scope.stackedBars are the objects which are linked to the graphs and they get updated, depending on which division the user clicks on (CPD is a division and there is only 4 divisions)

  1. The UI is updated…but the print result is not.
    Canvas URL:
    http://localhost:8080/#/dashboardPDOUB
    Resulting Print URL:
    http://localhost:8080/print.pdf?url=http%3A%2F%2FLOCALHOST%3A8080%2F%23%2FdashboardPDOUB&orientation=Landscape&page-size=A4

Hi @gpool,

First on showALL, the idea would be to wrap it with a $timeout when reinitializing it like so:

$scope.showALL =false;

$timeout(function(){
  $scope.showALL = true;
}, 50);

The idea behind it is to let it be removed by angular on 1 cycle, and then let it be re-initialize on the another cycle (the 50 ms delay).

Then regarding your scenario, if the user will need to click on a button, the action or parameter of this button should be placed in the URL. There is a sample of codes within the Printing page that shows you how you can do that.

The final check of the page would always be when you press F5 or when you refresh the browser with that URL - it should show the page in how you wanted it to be.

Looking at the URL you have posted, it does not seem like you have parameterized the URL yet.

If you have a pop up that allows user to select a division, then ideally you would save this up in the URL like division=TOT_SIG or division=OGD0000, so that when the page is refreshed and you have detected that there is a division passed as a parameter in the URL, you would initialize your graphs with that.

Cheers!

Paul

Hi @plim,

Thanks for the explanation - I have gotten it to work and understand things way better now!

Regards,
Gerhard

1 Like