Bug 164146 - JavaScript Variables not working properly
Summary: JavaScript Variables not working properly
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: BIRT (show other bugs)
Version: 2.1.1   Edit
Hardware: PC Windows XP
: P3 normal with 1 vote (vote)
Target Milestone: Future   Edit
Assignee: Wenfeng Li CLA
QA Contact:
URL:
Whiteboard:
Keywords: plan
: 173879 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-11-10 12:42 EST by Jason Weathersby CLA
Modified: 2008-06-09 17:37 EDT (History)
4 users (show)

See Also:


Attachments
example report (17.41 KB, text/xml)
2006-11-10 12:43 EST, Jason Weathersby CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jason Weathersby CLA 2006-11-10 12:42:11 EST
If I create a global js variable in the initialize and then set its value in the on create of a row to something like
aaa += this.getRowData().getColumnValue("QUANTITYORDERED");
and then in the group footer I add a data item with a value of aaa, it produces 2 problems.
1 - it concates as strings althought the column is set to integer.
2 - it doesnt get the last quantity ordered.
Comment 1 Jason Weathersby CLA 2006-11-10 12:43:23 EST
Created attachment 53641 [details]
example report

attached example with the error
Comment 2 Wei Yan CLA 2006-12-19 21:50:51 EST
1. the aaa is not intialized, so it is a Object. use a += <int value> will change a to a string. The user should use a = 0 to initialize the variable to number explictly.

2. All data binding expression is evaluated when engine fetch a row. It is before any onCreate of the report item which uses that row. So for the footer, it will use the value just before the last row instead of after the last row.
Comment 3 Jason Weathersby CLA 2006-12-20 12:04:08 EST
1 - aaa was initialized as aaa = 0; 
This was done in the initialize method of the report.

2 - If this is the way it works it is absolutely useless to be able
have an onCreate event script set values for a group footer.  It is ok to have the data binding expression occur before the onCreate, but the group footer expression should be evaluated after the onCreate of all rows in the group.  If it doesnt function this way than the group footer appears totally arbitrary and makes no sense.

What you are saying is that all the rows but one execute the onCreate properly, but we throw the last one away when a group footer is used.
Comment 4 Wenfeng Li CLA 2006-12-20 17:07:52 EST
> 2. All data binding expression is evaluated when engine fetch a row. It is
> before any onCreate of the report item which uses that row. So for the footer,
> it will use the value just before the last row instead of after the last row.

Is the "last row" the data binding row or group footer row?  by the time group footer row is evaulated, all detail rows in this group should have been created already, correct?  hence aaa += this.getRowData().getColumnValue("QUANTITYORDERED");  should have been evaluated for all the details rows in this group before the group footer row is created?

Comment 5 Wei Yan CLA 2006-12-20 21:50:13 EST
in the report design, the 
aaa += this.getRowData().getColumnValue("QUANTITYORDERED")
is defined in the onCreate of the ROW ELEMENT, it is evaluated when engine creats the ROW ELEMENT.

The "aaa" is used in the data binding, it is evaluate while fetching the DATA ROW.

Engine will fetch the DATA ROW before create the ROW ELEMENT, so the evaluation sequence is:
1. binding expression.
2. onCreate.


Comment 6 Jason Weathersby CLA 2006-12-20 22:22:54 EST
1 - So if I define a variable in the initialize and I use the variable in onCreate on the row, it creates a new instance of the variable?

2 - Ok, but the value was used on the group footer, which should be after the last detail row.
Comment 7 Wenfeng Li CLA 2006-12-20 22:26:11 EST
I would like to reopen this issue, since it is not what typical user expected. Even if it is the way it is designed/implemented now, we need to find a solution/enhancement to avoid such confusion from the user's perspective.
Comment 8 Nigel CLA 2007-03-11 21:05:23 EDT
I experience exactly the same problem and frustrations as Jason.  

My work-arounds for 1) is:

row:on_create:

var en_pr = this.getRowData().getColumnValue("en_p" ) ;

group_count ++;

if (en_pr != null ) {
var en_pr_num = new Number(en_pr);
en_count ++;
en_tot += en_pr_num;
}

My workaround for 2) is:

Create a new grid to contain the summary data items to be displayed in the report below the group footer, ie at the same 'level' as and after the group.  The summaries then contain data for all items in the group (including the last row). 

My summary information is at the bottom of the report.  I haven't tried this for nested summaries.

I know this is messy, but at least it gives the correct answers.  

Interestingly, while trying to diagnose the problem I noticed that a data item 'Total.count(row["progress"]), Aggregate on All' in a group footer suffered an off by 1 error, and I suspect the other Total.* functions are also ignoring the last row!

It seems to me that there is little point in having group footers in their current form, if they can't take account of data from processing the last row. IMHO the engine should process the footer as a pseudo row in it's own right.  It is not an extension of the last row. Data for the footer can't validly be fetched before the last row has been processed.

That said, BIRT is an amazingly flexible product and I really do appreciate all your hard work.


Comment 9 Wei Yan CLA 2007-03-28 08:42:07 EDT
the data binding expression and onCreate are executed in two different scopes, we need find  new solution to distinguish them.
defer to RC0
Comment 10 Wei Yan CLA 2007-03-28 08:45:43 EDT
*** Bug 173879 has been marked as a duplicate of this bug. ***
Comment 11 Wenfeng Li CLA 2007-04-04 03:54:16 EDT
In BIRT engine design, expression in data binding are evaluated before the report item's onCreate() script are evaluated.  For example, if there is a data binding expression of resultsetCol1 = aaa, and a data item in the group footer is using this resultsetCol1, the data item will get the value of "aaa" during the data binding calculation.  Since BIRT engine will first calculate the data binding for a report item before calling the onCreate() of this same report item, resultsetcol1 in data binding will be set to aaa's value BEFORE the onCreate() of the report item is called.

The easy of use is that such data binding is created when user enter an expression for a data item automatically.  It is not clear to the user that he/she is creating a data binding, instead the UI suggests more like the data report item is being set to a global var, and it has nothing to do with the data binding.  Hence the expression for the data item should be evaluated WHEN this data item is being created.   However, BIRT engine doesn't know that the expression in the data binding is TIED to this data item, so it should not evaluate it until the data item is being creating.  In stead, Engine will try to calculate all the expression first.  

Solution to be discussed:  Can engine change the data binding calculation sequence to calculate one data row-->generate one table row-->calculate next data row...  Open issue for this solution:  if there is a chart in the group header that needs all the data rows for the group, DtE needs to prepare all the rows for the chart.  But when the chart in the group headers is being created, the detail rows in the group have not been created, so the onCreate() will not be executed.  In this case, the databinding expression that uses global var aaa that will be incremented in the onCreate() will be set to a value BEFORE it is incremented by each row()'s onCreate().  And once the dataBinding is evaulated, it will not be evaulated again in the group footer, hence the aaa show up in the footer will not include the increments made in each detail row's onCreate().

Need further investigation in how to address this conflicting requirement on data binding evaluation sequence.


Another possible solution is to allow data item to be set to an expression explicitly, and then a data item is set to an expression, such as using "value-of(aaa)" as the value string of the data item.  When the value of a data item has this string, instead of the row(resultsetCol1) string, We will not create a data binding for it. Instead treat it like a text item with a <value-of> "aaa" </> string.

A work around for this paticular report is to use text report item, instead of data item, to show the aaa value.  which is a manul way to implement the above solution.