JasperReports list + each record on new page - list

I have the following report in JasperReports jrxml, Detail section.
It is a list I get from Java containing 2 objects, both are being outputed on the first page, so each time test variable is called.
<detail>
<band height="200" splitType="Stretch">
<componentElement>
<reportElement key="table" style="table" x="0" y="49" width="500" height="140"/>
<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
<datasetRun subDataset="Data Set">
<datasetParameter name="REPORT_DATA_SOURCE">
<datasetParameterExpression><![CDATA[$P{REPORT_DATA_SOURCE}]]></datasetParameterExpression>
</datasetParameter>
</datasetRun>
<jr:listContents height="50" >
<textField isBlankWhenNull="true">
<reportElement x="0" y="0" width="200" height="20" isRemoveLineWhenBlank="true"/>
<textElement textAlignment="Left" verticalAlignment="Middle" >
<font size="10" fontName="DejaVu Serif" isBold='true'/>
</textElement>
<textFieldExpression><![CDATA[$F{test}]]></textFieldExpression>
</textField>
</jr:listContents>
</jr:list>
</componentElement>
</band>
</detail>
So i have a list of 2 objects, beans. Everything works but this test variable gets shown twice on each page (both objects gets called on first page) instead of one object per page. I would like to put a break after first test is printed, so the next test in the list is printed on the next page.
Can anyone point me in the right direction?

I have the answer and i will post it here if someone else has the same problem.
Jasper report is quite buggy. First, when you are printing out collection of the elements (objects), you send collection to the jasper engine, which for some unknown reason doesnt recognize the first element in the collection. You solve this by adding one dummy object on the index 0 of your collection.
After searching i ve found out that jasper API has the function getPages(). This returns number of pages that there will be printed out, in a list. Each index of list is one page. You can call this function from this jasperPrint when u fill report.
JasperReport jasperReport = null;
JasperPrint jasperPrint = null;
where ist is the input stream of your jrxml, parameters is a hashmap, and last is your list of your jRBeancollData source.
beanColDataSource = new JRBeanCollectionDataSource("YOURLIST");
jasperReport = JasperCompileManager.compileReport(ist);
jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, beanColDataSource);
List<JRPrintPage> pages = japserPrint.getPages();
After you have this jasperPrint, you can call this function i wrote.
/**
* This removes blank page if the page size is bigger then the number of
* "pages" in array if for some reason we get last page as empty in pdf - we
* also put arraySize - 1 since we ve put one dummy(empty) in the array
* collection on index 0 since for some buggy unknown reason jasper always
* outputs collections from index 1 forward instead of 0.
*
* #author Uros
* #param pages
* , arraySize
*/
private void removeBlankPage(List<JRPrintPage> pages, int arraySize)
{
int numOfPages = pages.size();
if (numOfPages > arraySize - 1)
{
pages.remove(numOfPages - 1);
}
}
The function in this case removes only the last page, you can modify it so it removes any other empty page if there is one, and arraySize is smaller by one since you ve put in 1 dummy.
Since you print each object on each page, if there are more pages then objects, it is obvious there is one empty page so you remove it. You need to make sure that data wont stretch over to the next page ofcourse, but i print pages that will always look the same.
Hope it helps..

Yes put break page palette after printing your first object. So that it will print both
object in different pages.

I design my reports in iReport, which allows me to drag and drop a page break into the detail band, but maybe this can help you. The resulting XML looks like:
<break>
<reportElement uuid="*uuid here*" x="0" y="28" width="100" height="1"/>
</break>
</band>
</detail>
I inserted mine at the bottom of the detail band, so you should try inserting your <break> between your two objects.

Use a SubReport. Feed your list as a JRBeanCollectionDataSource to a SubReport. Place that subreport in the detail band along with a page break just below the subreport.
<break>
<reportElement uuid="*uuid here*" x="0" y="28" width="100" height="1"/>
</break>

Related

Pass id or class name to points(ticks) inside canvas

I am using react-chartjs-2 to render charts and on clicking the active point it gets redirected to some other page.
<Line
id={'chartid'}
data={data}
options={options}
getElementAtEvent={dataset => {
// redirects to some other page
}}
/>
Sample chart
We are doing automation testing and need to check if click is working or not.
Is there any option to add id/class to active elements inside the rendered canvas. Can anyone help?
AFAIK every element has got datasetIndex and index properties related to the drawn dataset.
Emitting the click event on the canvas (a specific point) you could check that dataset index and index are what you are expecting

Each bound to array displays only the first item

I am building an Ember App. I have the following in my template :
{{#if App.selected}}
<p class="small-desc">{{App.selCount}} product added to list</p>
{{#each App.selected}}
{{button-custom action="removeFromList" params=this close="true" class="col-xs-12" text=this}}
{{/each}}
{{button-custom action="proceedToDetails" class="col-xs-12" color="red" text="Next"}}
{{/if}}
Here App.selected is an Array []. When a product is selected, it is added to the Array. At the first click, the item(selected) is added and is displayed on the browser. When the next product is clicked, there is no visible change in the browser. But using the console I have checked and ensured that the new product was added to App.selected. But Ember displays only the first one.
Due to the very odd nature of this problem and fruitless searches made on Google, I am posting this as a question here.
Additional info -
NOTE: App is not the Ember application. It's just a variable
I populate App.selected as :
a = App.selected;
a.push('name');
Ember.set(App, 'selected', a);
button-custom is a component that uses 'text' as its caption.
If I visit the same route without reloading(after selecting more than 1 products), all the items in the array are displayed correctly.
Other {{#each}}'s that are bound to different arrays on the same page work as they should.
I tested the #each block on other routes too. Everywhere its the same. I replaced button-custom with plain text 'asd' and it exhibits the same behavior. (My intuition tells me I have made some mistake, a very silly one!)
The array is declared as :
App = {
selected : null
}
The controller for this template is an ObjectController. Initially, #each was bound to selected property of the controller. But when that didn't work, I bound it to an array in namespace App. The results were the same, then and now.
UPDATE
It seems that each will not always iterate over an array. Suppose an #each block over variable Arr. If Arr is null, #each displays nothing. When you set Arr to any array(empty or populated), then Ember renders the contents of Arr. But this happens only the first time. The next time you set Arr to another array, Ember will not repopulate #each, unless you set it to null.
Ember does not guarantee best results with a JS array. So I had to change my array to Ember Mutable Array :
App.Search = {
selected = Ember.A([]);
}
And then, as #blessenm suggested, add to the array with pushObject :
a = App.Search.selected;
a.pushObject('product');
Ember.set(App.Search, 'selected', a);
To remove from array :
a = App.Search.selected;
a.removeObject('product');
Ember.set(App.Search, 'selected', a);

Goutte with behat: xml string as textarea value is filled with html entities

I have a page that contains a form with some input elements, including a textarea. Those input fields are populated with some values. Think of this whole page as an edit page for some entity. Textarea contains an XML string that shows properly within normal browser (eg. firefox and chrome) and looks like following:
<front>
<!-- top row -->
<cell>
<page>8</page>
</cell>
</front>
But when i run the test case with goutte mink driver the page is loaded and the value of textarea is encoded with special characters, like so:
<front>
<!-- top row -->
<cell>
<page>8</page>
</cell>
</front>
And when i press submit button that mess is sent to the server and saved instead of initial correct xml. Note that i do not touch it at all. I can just load the page and press submit button and it's all screwed. This happens only with goutte, but not with, say, selenium2.
So the question is: how can i force goutte interpret those html entities automatically and send them as correct data, not that encoded mess?
there's no solution for that. It seems as normal behavior of Goutte/Guzzle. As a workaround we ended up with following solution: in case Goutte driver is used we check page contents for all <textarea> elements, and if any found then for each we get their contents and plainly reinsert as follows:
$elements = $this->pageContent->findAll('xpath', '//textarea');
foreach ($elements as $element) {
$element->setValue($element->getText());
}

Obtaining visible text on a page from an IHTMLDocument2*

I am trying to obtain the text content of a Internet Explorer web browser window.
I am following these steps:
obtain a pointer to IHTMLDocument2
from the IHTMLDocument2 i obtain the body as an IHTMLElement
3. On the body i call get_innerText
Edit
I obtain all the children of the body and try to do a recursive call on all the IHTMLElements
if i get any element which is not visible or if i get an element whose tag is script, i ignore that element and all its children.
My problem is
that along with the text which is visible on the page i also get content having for which style="display: none"
For google.com, i also get javascript along with the text.
I have tried a recursive approach, but i am clueless as to how to deal with scenarios like this,
<div>
Hello World 1
<div style="display: none">Hello world 2</div>
</div>
In this scenario i wont be able to get "Hello World 1"
Can anyone please help me out with the best way to obtain the text from an IHTMLDocument2*.
I am using C++ Win32, no MFC, ATL.
Thanks,
Ashish.
If you iterate backwards on the document.body.all elements, you will always walk on the elements inside out. So you don't need to walk recursive yourself. the DOM will do that for you. e.g. (Code is in Delphi):
procedure Test();
var
document, el: OleVariant;
i: Integer;
begin
document := CreateComObject(CLASS_HTMLDocument) as IDispatch;
document.open;
document.write('<div>Hello World 1<div style="display: none">Hello world 2<div>This DIV is also invisible</div></div></div>');
document.close;
for i := document.body.all.length - 1 downto 0 do // iterate backwards
begin
el := document.body.all.item(i);
// filter the elements
if (el.style.display = 'none') then
begin
el.removeNode(true);
end;
end;
ShowMessage(document.body.innerText);
end;
A Side Comment:
As for your scenario with the recursive approach:
<div>Hello World 1<div style="display: none">Hello world 2</div></div>
If e.g. our element is the first DIV, el.getAdjacentText('afterBegin') will return "Hello World 1". So we can probably iterate forward on the elements and collect the getAdjacentText('afterBegin'), but this is a bit more difficult because we need to test the parents of each element for el.currentStyle.display.

How To I Replace New Elements Added To A Page With Jquery

Here is the scenario... I have a a checkbox next to each field that I am replacing on page load with jquery with "Delete" text that enables me to delete the field via jquery, which is working fine. Like so...
$(".profile-status-box").each(function(){ $(this).replaceWith('<span class="delete">' + 'Delete' + '</span>') });
The problem comes in however is that after page load, I am also giving the user the option to dynamically add new fields. The new added fields though have the checkbox and not the delete link because they are not being replaced by jquery since they are being added after the initial page load.
Is't possible to replace the content of new elements added to the page without doing a page refresh? If not, I can always have two templates with different markup depending one for js and one for non js, but I was trying to avoind taht.
Thanks in advance.
You can use the .livequery() plugin, like this:
$(".profile-status-box").livequery(function(){
$(this).replaceWith('<span class="delete">Delete</span>')
});
The anonymous function is run against every element found, and each new element matching the selector as they're added.
Have a look at this kool demo. It removes and adds elements like a charm.
http://www.dustindiaz.com/basement/addRemoveChild.html
Here's how:
First of all, the (x)html is real simple.
xHTML Snippet
<input type="hidden" value="0" id="theValue" />
<p>Add Some Elements</p>
<div id="myDiv"> </div>
The hidden input element simply gives you a chance to dynamically call a number you could start with. This, for instance could be set with PHP or ASP. The onclick event handler is used to call the function. Lastly, the div element is set and ready to receive some children appended unto itself (gosh that sounds wierd).
Mkay, so far so easy. Now the JS functions.
addElement JavaScript Function
function addElement() {
var ni = document.getElementById('myDiv');
var numi = document.getElementById('theValue');
var num = (document.getElementById('theValue').value -1)+ 2;
numi.value = num;
var newdiv = document.createElement('div');
var divIdName = 'my'+num+'Div';
newdiv.setAttribute('id',divIdName);
newdiv.innerHTML = 'Element Number '+num+' has been added! <a href=\'#\' onclick=\'removeElement('+divIdName+')\'>Remove the div "'+divIdName+'"</a>';
ni.appendChild(newdiv);
}
And if you want to,
removeElement JavaScript Function
function removeElement(divNum) {
var d = document.getElementById('myDiv');
var olddiv = document.getElementById(divNum);
d.removeChild(olddiv);
}
and thats that. bobs your uncle.
This is taken from this article/tutorial: http://www.dustindiaz.com/add-and-remove-html-elements-dynamically-with-javascript/
I've just learnt this myself. thank you for the question
Hope that helps.
PK