Customizing dialogs to perform web actions

Currently JReport enables customizing a dialog to perform web actions such as sorting and filtering in a table of a page report at runtime, by using customized controls.

A customized control is a user defined web action dialog containing normal web controls that can process actions. The report designer first defines a customized control to be triggered from a component in a page report table in JReport Designer and then publish the report to JReport Server. Next the server end users can trigger the customized control which is shown as a dialog to perform web action as defined in the report.

In JReport Designer, you can store the properties of a customized control into a file with the extension .wctrl to the customized control library which is the Customized Control folder under the installation root. JReport Server saves customized controls in DBMS.

Customized controls do not take part in the report layout and are not exported in the report results.

Defining customized control in JReport Designer
  1. Right-click an object as a trigger in a table in a page report, for example, a column header label, and select Display Type from the shortcut menu.
  2. In the Web Behaviors box of the Display Type dialog, choose an event from the Events column, for example, Click, then click in the Actions column and click  that appears in the text box.
  3. In the Web Action List dialog, select Customized Control to bind a customized control web action, or select Customized Control from Lib to reference a file from the library, and then click OK.
  4. Click OK in the Display Type dialog to finish.

Next publish the report to JReport Server. Run the report on the server, click the triggered column header label, a dialog will be displayed for performing web actions.

Managing customized controls

You can manage the properties of a customized control and the customized control files in the customized control library using the Customized Control Manager.

To open the Customized Control Manager, click Edit > Customized Control Manager on the menu bar. See the manager.

In the Customized Control Manager, you can perform the following:

Creating a new customized control file

Click the  button, provide a name to the new file in the New Customized Control File dialog, and then define the customized control properties in the Customized Control – Web Action Builder dialog.

Editing a customized control file

Right-click the file and select Edit from the shortcut menu. Then modify the customized control properties in the Customized Control – Web Action Builder dialog.

Renaming a customized control file

Right-click the file and select Rename from the shortcut menu. Input a new name and then click outside of the name area to accept the change.

Creating a copy of a customized control file

Right-click the file and select Duplicate from the shortcut menu. A copy will be created and listed in the manager. You can then change the name of the copy file and the properties of the customized control.

Removing a customized control file

Select the file and click . Or right-click the file and select Delete from the shortcut menu.

Sorting the customized control files

By default the customized control files are listed in the ascending order according to their names. Click  and the files will be in the descending order. Next you can click  to change the order back to ascending.

Note that the descending order will not be remembered after you click OK and exit the dialog. The next time you access the dialog it is always the ascending order.

Sample of customized control contents

Copy all the following codes as the contents of a customized control:

<style>
#plugin {
background-color: gray;
}

#plugin td {
background-color: white;
}

.item--available {
}

.item--unavailable{
color: #CCCCCC;
}

</style>
<table id="plugin" cellspacing="1px" style="margin:0px;width:100%;height:300px;border:1px solid silver;background-color:;">
<tr style="height:30px;"><td>
<table style="text-align:center;width:100%;background-color:;">
<tr>
<td><button id="btnSortA" onclick="this.doSort('Ascending')">Ascending</button></td>
<td style="border-left:1px solid gray;"><button id="btnSortD" onclick="this.doSort('Descending')">Descending</button></td>
</tr>
</table>
</td></tr>
<tr style="height:25px;"><td style="background-color:#cccccc;padding:3px;">
<input id="searchbox" style="width:85%;margin-right:3px;" type="text" onkeyup="this.search(e)"/>
<div style="width:10px;height:19px;float:right;cursor:pointer;"
onclick="this.clearSearch()">x</div>
</td></tr>
<tr style="height:150px;"><td>
<div id="fc-values" onclick="this.selectValue(e)" style="width:100%;height:150px;overflow:auto;"></div>
</td></tr>
<tr style="height:30px;">
<td style="background-color:#cccccc;"><button onclick="this.doFilter()">Apply</button><button onclick="this.clear()">Clear</button></td>
</tr>
</table>

<script type="text/javascript">


var comp; // data container
var field; // db field
var filter;

var _onGetDataContainer = function(msg){
var result = msg.result;
if(result.err == 0){
comp = result.obj.comp;
if(!comp) return;
comp.getAssocDBField(context.dsid, _onGetDBField);
}else{
System.err.println(result.msg);
throw new Error(result.msg);
}
}.$bind(this);

var _onGetDBField = function(msg){
var result = msg.result;
if(result.err == 0){
field = result.obj.field;
// TODO enable sort ?
Report.getFilterCtrl(field, comp, _onGetFilterCtrl);
}else{
System.err.println(result.msg);
throw new Error(result.msg);
}
}.$bind(this);

var _onGetFilterCtrl = function(msg){
var result = msg.result;
if(result.err == 0){
filter = result.obj.ctrl;
if(!filter) return;
// TODO enable filter ?
_renderValues.call(this, filter);
}else{
System.err.println(result.msg);
throw new Error(result.msg);
}
}.$bind(this);

var _canSort = function(){
var b = !!comp && !!field;
return b ? comp.isSortable() : false;
};

var _canFilter = function(){
var b = !!comp && !!field && !!filter
return b ? comp.isFilterable() : false;
};

var _renderValues = function(filter, values){
var td = document.getElementById("fc-values"),
i, len, val, item, buf, showAll;

showAll = !values;
values = values || filter.getAllValues();
td.innerHTML = "";
var isAll = filter.isAllSelected();
for(i=showAll ? -1:0, len=values.length; i<len; i++){
val = i < 0 ? {disp:"All", real:"__ALL__", selected:isAll, available:true} :
values[i];
item = document.createElement("LI");
item.className = val.available ? "item--available" : "item--unavailable";
buf = ["<input type='checkbox' id='fc-index-",i,"' "];
buf.push("value=\"", val.real, "\"");
if(val.selected){
buf.push("checked");
}
buf.push("/>", val.disp);
item.innerHTML = buf.join("");
td.appendChild(item);
}
};

this.doSort = function(type){
if(!_canSort()) return;
comp.sort(field, type);
};

this.selectValue = function(e){
e = e || window.event;
var ele = e.srcElement||e.target, key, checked;
if(ele.tagName != "INPUT") return;
key = ele.value;
checked = ele.checked;
if("__ALL__" === key){
filter.selectAll(checked);
_renderValues.call(this, filter);
}else{
filter.select(key, checked);

// The element for 'All' should be updated checked status
ele = document.getElementById("fc-index--1");
if(filter.isAllSelected()){
ele.checked = true;
}else{
ele.checked = false;
}
}
};

this.doFilter = function(){
if(!_canFilter()) return;
filter.applyFilter();
this.hide();
};

this.clear = function(){
if(!filter) return;
filter.clearSelects();
_renderValues.call(this, filter);
};

this.search = function(e){
if(!filter) return;
e = e || window.event;
var ele = e.srcElement||e.target, value = ele.value, values;
if(value){
values = filter.search(value);
}
_renderValues.call(this, filter, values);
};

this.clearSearch = function(){
document.getElementById("searchbox").value="";
if(!filter) return;
_renderValues.call(this, filter);
};

Report.getDataContainerBy(context.dsid, _onGetDataContainer);

</script>

The dialog looks like as follows:

x
Related topics: