Home
Analytics
Javascript variable scope issue
TDub
<p>I'm having an issue with some javascript I'm using. I'm declaring some variables and functions in initialize, building the array using those (global, right?) functions in initialize and then calling a function in afterFactory that sorts the array and stores it in another array variable. I know the function is working properly because I can log the array elements from afterFactory and everything is how I would expect it, but then when I try to access the arrays with a dynamic text box in the report, the sorted array is empty and the original array (which is global and has had all the elements removed by the function) is still full.<br />
<br />
I'm suspecting that BIRT handles variable scope in a way that I don't fully understand, because the original array that's built in onFetch has no problems being accessed by the report, just the array that's being changed in afterFactory isn't keeping the changed elements.<br />
<br />
Here's the JS I have in the different sections. Thanks.<br />
<br />
<span class='bbc_underline'><strong>Initialize</strong></span><br />
</p><div>var med_array = [];</div><div>//var sorted_array = [];</div><div>var final_array = [];</div><div>var test_array = [];</div><div>var janChange = "";</div><div>var test = 2;</div><div> </div><div>function Medication(name, start_date, stop_date, modified_date, strength, row_num){</div><div> this.name = name;</div><div> this.start_date = start_date;</div><div> this.stop_date = stop_date;</div><div> this.modified_date = modified_date;</div><div> this.strength = strength;</div><div> this.row_num = row_num;</div><div>}</div><div> </div><div>function sort_array(unsorted_array){</div><div> var groupNum = -1;</div><div> var sorted_array = [];</div><div> while(unsorted_array.length > 0){</div><div> if(unsorted_array[0].row_num == 1){</div><div> groupNum++;</div><div> sorted_array[groupNum] = [];</div><div> }</div><div> sorted_array[groupNum].push(unsorted_array.shift());</div><div>}</div><div> </div><div>return sorted_array;</div><div>}</div><p> </p><p><strong><span class='bbc_underline'>onFetch</span></strong><br />
<br />
med_array.push( new Medication(row["MEDICATION"], row["DATEPRESCRIBED"], row["DATESTOPPED"], row["LAST_MODIFIED"], row["DOSAGE"], row["ROW_NUM"]));</p><p> </p><p><strong><span class='bbc_underline'>afterFactory</span></strong></p><p> </p><p>final_array = sort_array(med_array);<br />
<br />
<span class='bbc_underline'><strong>BIRT Report dynamic text box</strong></span></p><p> </p><p>"Test" + " " + final_array[0] + " " + med_array[0] + " " + test<br />
<br />
</p>
Find more posts tagged with
Comments
wwilliams
<p>try removing the var, if I am still lucid, declaring with the var in the initialize makes it local.</p><div style="margin:0px;color:rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;"> med_array = [];</div><div style="margin:0px;color:rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;">//var sorted_array = [];</div><div style="margin:0px;color:rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;"> final_array = [];</div><div style="margin:0px;color:rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;"> test_array = [];</div><div style="margin:0px;color:rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;"> janChange = "";</div><div style="margin:0px;color:rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;"> test = 2;</div>
micajblock
<p>Also do not use the initialize method (gets call twice, once for the generation task and once for the render task), use the beforeFactory instead.</p>
TDub
<p>I forgot to mention that I'm using BIRT version 2.3.1 if that matters.
I moved the variable declarations to beforeFactory and removed the leading 'var' from each, but it's still doing the same thing. At first I tried moving the function declarations to beforeFactory as well, but I would get errors that the functions weren't defined, even though none of them are called before beforeFactory, so that seemed odd and when I moved just the functions back to initialize it ran the report.
Thanks for your help so far! Any ideas now?</p>
micajblock
<p>What is your code in the dynamic Text. It is possible that it is executed at render time so the array is not available. you might need to create a global persistent variable to be available for both generation and render tasks. </p><p> </p><p>Functions are reportContext.setPersistentGlobalVariable() and reportContext.getPersistentGlobalVariable()</p>
TDub
<p>Dynamic text is [color=rgb(40,40,40);font-family:'Source Sans Pro', sans-serif;]"Test " + final_array[0] + " " + med_array[0] + " " + test<br />
<br />
That makes sense that the render is a separate scope from the generation. I'll try it with the reportContext functions and see how that works. Do you know why it's still able to output information for the med_array? In the dynamic text box, the med_array outputs the array elements that are put into it during the onFetch for the dataset, but by that point, the sort_array function should have removed them and med_array should be empty. Especially so if the generation and render are separate. Since the onFetch event happens during the generation phase, why would it still be able to access them? Is it because it was in a dataset event rather than a report event? I'm trying to understand how it all relates.[/color]<br />
<br />
</p>
micajblock
<p>This video might be helpful</p><p> </p><p><a data-ipb='nomediaparse' href='
https://www.youtube.com/watch?v=FQ9VjByPNWM'>https://www.youtube.com/watch?v=FQ9VjByPNWM</a></p>
TDub
<p>Even using the set and get persistent variable, the array is still retaining the information that gets put into it in onFetch. I feel like I understand the flow of the events, which is why this is so weird. It's being modified in onFetch with med_array.push() and for some reason, that's the only step that's doing anything that sticks. I don't get how the changes made in onFetch can still be there after afterFactory executes, because afterFactory happens later than onFetch. It's like afterFactory is somehow executing within a very limited scope, which doesn't make any sense to me, because I've tried putting the function call in beforeClose as well, which is on the same level as onFetch, but still nothing sticks after that.</p>
micajblock
<p>Can you create a simple version of your problem that I can run?</p>
TDub
<p>Here's a report that I put together with the sample database. I had to change the sort function a bit to make it work in a similar way to mine, but it should basically be the same. The only difference is that on this one, nothing is in the array at all when it's being output in the report, whereas in my original, it's basically outputting the contents of the array as it is after onFetch but before afterFactory. In the afterFactory event, the array size is 2996 before the sort and 326 after, which tells me it's definitely sorting, just like in my main one, it's just not accessible in the report for whatever reason.
Hopefully it's something simple that I've just been overlooking or not doing correctly, because this issue has been driving me up a wall. Thanks again for all your help.</p>