Visualize.js – Hyperlinks API

Visualize.js – Hyperlinks

In the post, we will discuss how we can handle hyperlink execution in jaspersoft reports that are embedded using visualize.js.

If you have not worked on rendering reports through visualize js , this post may not be the best place to start. You may check this one out.

As we all know, jasper hyperlink’s are of various types – report execution, reference, local / remote anchor or pages. We will look into what information do we get about the hyperlinks in the embedded reports when we click on them and how we can utilize this information to take appropriate action on the event.

As an example, we will take one of the sample report from the jasper samples that come with the installation – SalesByMonthReport. I have made a small change to this report and added a hyperlink in the page footer of the type “reference” which opens “http://helicaltech.com/” webpage.

RenderedReport1

Below is the HTML and the Java Script Code for embedding the report using Visualize JS with hyperlink handling –
—- HTML —–

<!----- JQuery,underscore js is required for this code, has been included from external resources in jsfiddle--->
<script type='text/javascript' src="http://192.168.2.141:8082/jasperserver-pro/client/visualize.js"></script>
<div id="container"> Main report Appears here</div>
<div id="container2">Drilldown Appears here</div>

 I have created 2 place holder divisions, “container” to render the “SalesByMonthReport” report. This report has a drilldown report which opens when we click on any of the months in the table. When user clicks on any of these hyperlinks, we will display the drilldown report in “container2”

— Java Script —

var reportUri = "/public/Samples/Reports/SalesByMonthReport"
visualize({
    auth: {
        name: "superuser",
        password: "superuser"
    }
}, function (v) {
   var report = v.report({ 
        resource: reportUri, 
        container: "#container", 
        params:{"startMonth": ['1'],"endMonth": ['12']},  //defaults
        linkOptions: {
       	   beforeRender: function (linkToElemPairs) {
                linkToElemPairs.forEach(showCursor);
            },
            events: {
                "click": function(ev, link){
                    console.log(link);
                  if(link.type == 'ReportExecution'){
                  		v("#container2").report({
                            resource: link.parameters._report,
                            params: {
                                monthNumber: [link.parameters.monthNumber]
                            }, 
                        });     
                  }
                  else if(link.type == 'Reference'){
                  	window.open(link.href);
                  }
                }
            }    
        },
        success:function () {
            alert('Report rendered successfully');
        },
        error: function (err) {
            alert(err.message);
        }  
    });
    
   function showCursor(pair){
           var elink = pair.element;
               elink.style.cursor = "pointer";
    }
});

  Let’s concentrate on the “linkOptions” portion of the call to the Report API. It allows you to control the behaviour of the Hyperlinks.

beforeRender: function (linkToElemPairs) {
    linkToElemPairs.forEach(showCursor);
}

  In “beforeRender”, we are just trying to change the cursor type when mouse moves over the element which has the hyperlink. I am not going into details of this code. However, we can see that there is a way to add any logic that might be required before the links are rendered.

events: {
            "click": function(ev, link){
				console.log(link);
				if(link.type == 'ReportExecution'){
					v("#container2").report({
						resource: link.parameters._report,
						params: {
							monthNumber: [link.parameters.monthNumber]
						}, 
					});     
				}
				else if(link.type == 'Reference'){
					window.open(link.href);
				}
			}
	}

  In “events”, we can define the behaviour in case of various events, mainly the click event. Inside the click event callback function, we get access to the definition of the hyperlink on which click has happened. You basically get access to all the hyperlink properties that we define at design time.
In our example, we have 2 types of hyperlinks – report execution & reference. Lets see what we get for each of these types and what action we have taken on them using the information.

Report Execution : When user would click on the link on months in the table –

Hyperlink-Reference-report

Below is the JSON we get in the “link” parameter of the click callback (“click”: function(ev, link))

Hyperlink-ReportExecution

As you see, in our code, we check for “link.type” value and then in case it is “ReportExecution”, we use “link.parameters._report” & “link.parameters.monthNumber” values to call the Report API again and display the drilldown report in “container2”.

Reference : When user would click on the hyperlink in the page footer –

Hyperlink-ReportExecution-report

Below is the JSON we get in the “link” parameter of the click callback (“click”: function(ev, link))

Hyperlink-Reference

As you see, in our code, we check for “link.type” value and then in case it is “Reference”, we use “link.href” to open the hyperlink in a new window.

So, with this, we have successfully handled 2 different types of Hyperlinks that we come across in reports. Similarly, you can also write your logic to handle the other types as per your requirement.

JS fiddle of the example : http://jsfiddle.net/b42ax3m2/63/

You may also check the below blog links for learning about – authentication, report rendering, input controls API of visualize JS.
First encounter with Visualise.js
Visualize.js – The Input Controls API

References:
Visualize JS API reference

– Shraddha
Helical IT Solutions

Visualize.js – The Input Controls API

Visualize.js – The Input Controls API

In my first blog about visualize.js, we looked at the basics, a small introduction of the API with example. The example covered 3 basic things – authentication, report rendering and sending parameters to the report. In this blog, I am planning to look into the API for the Input Controls, as those are one of the basic building blocks of the reports. What information about the input controls can we access through this API? How can it be utilized to render/display similar input controls on the embedded report?

Let’s explore this with an example –
I am taking the same report as from the previous blog as an example. It is a simple report which displays Product Sales for a selected store. It has 2 input controls – ‘State’ (id : ip_state) and ‘StoreID’(id: ip_storeid). The ‘StoreID’ cascaded on ‘State’.

Visualize.js API to access the input controls

The API gives you all the input controls defined on the report along with its metadata information including the reference to cascaded input controls, both parent/children.
API to access input controls on a report looks like

visualize({auth: {...}}, function (v) {
    var inputControls = v.inputControls({
        resource: "/public/MyReports/Test1",
        params:{"ip_state":["WA"]},
        success: renderInputControls
    });

resource – is the uri of the report for which the input controls are to be fetched.
params – provide parameter values for the input controls. This is in case of cascaded input controls, you may want to provide a specific value for input parameter for the cascaded control.
In our example above, we have passed the value for ‘State’ as “WA” and the ‘StoreID’ input control will utilize this parameter value and return the values accordingly.

What information about the input controls can we access through this API? – The input controls Array

The response to this API is a JSON Array which is an array of Input control objects. Each object gives information for a single input control. Below is the response for the sample report –

"inputControl" : [{
			"id" : "ip_storeid",
			"type" : "singleSelect",
			"uri" : "repo:/public/MyReports/Test1_files/ip_storeid",
			"label" : "Store ID",
			"mandatory" : false,
			"readOnly" : false,
			"visible" : true,
			"masterDependencies" : ["ip_state"],
			"slaveDependencies" : [],
			"state" : {
				"uri" : "/public/MyReports/Test1_files/ip_storeid",
				"id" : "ip_storeid",
				"options" : [{
						"selected" : false,
						"label" : "---",
						"value" : "~NOTHING~"
					}, {
						"selected" : false,
						"label" : "Store 2",
						"value" : "2"
					}, {
						"selected" : true,
						"label" : "Store 17",
						"value" : "17"
					}.........
				]
			}
		}, {
			"id" : "ip_state"....
			"masterDependencies" : [],
			"slaveDependencies" : ["ip_storeid"],
			...............
		}
	]
}

How can it be utilized to render/display similar input controls on the embedded report?

In the example below, I have utilised the “Options” in the API response object to display in a selection list in my HTML page. The renderInputControls() is defined as a “success” callback in the “inputControls()” API call. The report() function is invoked to render the report with default parameters.

HTML Code:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript " src="http://localhost:8081/jasperserver-pro/client/visualize.js "></script>
<div id="container ">Embedded a Sample Report</div>
<select id="stateselector"></select>
<select id="storeidselector"></select>
<div id="testreport"></div>

JavaScript Code

visualize({ auth: {..}}, function (v) {
    var inputControls = v.inputControls({
        resource: "/public/MyReports/Test1",
        params:{"ip_state":["WA"]},
        success: renderInputControls
    });
    var report = v.report({
        resource: "/public/MyReports/Test1",
        container: "#testreport",
        params: {"ip_state":["WA"], "ip_storeid": ["17
    });

    $("#stateselector").on("change", function () {
        inputControls.params({ "ip_state":[$(this).val()] })
        .run(function (data){renderInputControlStoreID(data);});
    });
    
    $("#storeidselector").on("change", function () {
        report.params({"ip_state":[$("#stateselector").val()],"ip_storeid": [$(this).val()]}).run();
    });
});

function renderInputControls(data) {
    renderInputControlState(data);
    renderInputControlStoreID(data);
}

function renderInputControlState(data) {
    var stateInputControl = _.findWhere(data, {id: "ip_state"});
   
    var select = $("#stateselector");
    _.each(stateInputControl.state.options, function (option) {
        select.append("" + option.label + "");
    });
}

function renderInputControlStoreID(data) {
    var storeidInputControl = _.findWhere(data, {id: "ip_storeid"});
    
    var select = $("#storeidselector").empty();
    _.each(storeidInputControl.state.options, function (option) {
        select.append("" + option.label + "");
    });
} 

Cascading the input controls
In above example, the function defined on change of “stateselector”, refreshes the “storiedselector” by invoking “inputControls.params()” with new value of “ip_state” to get new values for “ip_storeid”. It then invokes “renderInputControlStoreID()” to render new values in “storeidselector”.

Refreshing the Report with the new parameters
In the example, the function defined on change of “storeidselector” refreshes the report. It invokes the “report.params()” function of visualize.js with new parameter values.

Though this example is not a very good one, it covers the basic flow. The information in the API could be utilized much more effectively to dynamically embed and cascade the input controls in your native page.
Hope this gives you a good start-off though!!

References:

1) JS fiddle for the example in the report
2) http://community.jaspersoft.com/wiki/visualizejs-api-notes-and-samples

– Shraddha
Helical IT Solutions