Firstly, I must admit that this has never happened before in all of the several portlets done in the past.
We have an Async Table rendered on a Page with sorting enabled on the columns. When a sort link on any of the columns is clicked, the Table “refreshes” and goes blank. There is a Javascript error on line # 11908 in general.js with the error described as below when this happens.
Uncaught TypeError: Cannot call method ‘getFirst’ of null
registerAddRemoveListener:function(tableId,id,standardMsg,emptyMsg,atEndMsg,beyondEndMsg,unknownTotalMsg){
setTimeout(function(){
if(CAF.DataTotal.listeners[id])
return;
var fn=CAF.DataTotal.listeners[id]=function(){
var table=$(tableId);
var m=CAF.model(tableId);
var first=m.getFirst();
var last=first+m.size();
var total=m.getRowCount();
var msg=standardMsg;
Above is an extract of javascript code above and below the line that fails. Looks like “m” is not able to get a handle on the table and consequently, its getFirst() method fails.
The table was rendered directly from the output of a webservice without using a content provider. I thought this may be the cause and so I created a Selectable, Sortable, Updateable and other “ables” Content Provider and bound it to the Table. The problem still persists.
The only other difference between other portlets with tables and this one is that there are 5 tables in this and only one of them is “rendered” based on a condition.
Firstly, Wish All members of the Forum, A Very Happy, Healthy and Prosperous New Year and Decade.
I actually figured out the problem. Because I was conditionally setting the rendered property of the 5 tables based on a parameter fed into this portlet, the Javascript in general.js was expecting that the tables exist on the page and was trying to initialize some of the listeners on these tables.
With my limited knowledge on DOM and JS and HTML elements and all of them put together (sure is a heady mix for me!!), I hazard a guess that the JS knows that there are tables out there and it has to work on them, but the rendered properties of table make sure that DOM objects are not created??? I could be a 100% wrong on this.
So, the workaround or perhaps the Best Practice is to wrap controls in Hideable Panel and set its visible property conditionally.
Unfortunately, there appears to be something else as well that is causing this behaviour. The workaround works, however, if the page has been left “unattended” for a while and then you perform any Async actions (or perhaps even actions) like Sort, Export Table, then the table becomes empty again with just the Column Headers displayed. And no, the page was not idle enough to have hit the timeout value.
I look at the HTML Page source, and all the Table rows are still there. Also, the Table Empty Message appears at the Table Footer.
Hi
have you tried to create a local variable in your view to get the output of the web service and bind that variable to your table’s value?
I would also put your 5 tables inside a hideable panel (always visible), set the rendered property of your tables to whatever condition you have and refresh only the hideable panel.
I had the same webservice output bound to two tables and one was always hidden in a hideable panel as I was experimenting it with Categorized Table and Tree Tables. I believed that no harm is done if a table control is hidden in a hideable panel while the same data is “visible” in another table.
Perhaps that is the reason when any action is performed on the visible table, it conflicts with the other table and data seems lost.
I have deleted the other tables and yet the problem persists.
Are there any Client side JS Table Column Sort listeners. I would like to listen to this event and refresh the page before performing the Sort. And would like to do the same for Table Export, but unfortunately the control does not have client side events.
Okay, this time we definitely know the Exact reason why this is happening.
What we have is kind of a Report Parameters screen with different criteria to choose from. When you hit a Basic Navigation button, we open a new window with Report Parameters to a Portlet View (Lets call it Report.view).
Report.view has 5 tables wrapped in 5 hideable panels whose visible property is set based on the Report Name which is one of the parameters. And based on the Report Name, the appropriate webservice is called to fetch the data.
All is well when we open the first Report (say A). It sorts, it exports and does everything. The trouble starts when we open another different Report (say B). So, now we have 3 windows open, the Report Parameters, Report_A and Report_B. If I now go back to Report_A and do any action, it empties the table. I do a Browser Refresh ( F5 ) on Report_A and as expected it will call the webservice again and the data comes back. Now you go to Report_B and do a sort, it empties the table in Report_B.
Basically, only the latest instance of the Portlet view behaves as expected and previous instances of the same Portlet View refuse to behave.
The scope of the Portlet View is Request
Is this by design? How do we get around this without having to create separate views for each Report.
Thanks for your help in advance,
Best regards,
Raj
Okay, this time we definitely know the Exact reason why this is happening.
What we have is kind of a Report Parameters screen with different criteria to choose from. When you hit a Basic Navigation button, we open a new window with Report Parameters to a Portlet View (Lets call it Report.view).
Report.view has 5 tables wrapped in 5 hideable panels whose visible property is set based on the Report Name which is one of the parameters. And based on the Report Name, the appropriate webservice is called to fetch the data.
All is well when we open the first Report (say A). It sorts, it exports and does everything. The trouble starts when we open another different Report (say B). So, now we have 3 windows open, the Report Parameters, Report_A and Report_B. If I now go back to Report_A and do any action, it empties the table. I do a Browser Refresh ( F5 ) on Report_A and as expected it will call the webservice again and the data comes back. Now you go to Report_B and do a sort, it empties the table in Report_B.
Basically, only the latest instance of the Portlet view behaves as expected and previous instances of the same Portlet View refuse to behave.
The scope of the Portlet View is Request
Is this by design? How do we get around this without having to create separate views for each Report.
Thanks for your help in advance,
Best regards,
Raj
Thanks for the explanation… Quick question for you: Are the parameters passed via the URL?
Additionally, i want to clarify. You want to be able to open up multiple instances of this portlet (in different browser windows) and bounce back and forth between them, correct?
Meanwhile, I went ahead and created separate portlets for each Report and guess what, it works fine most of the time, but sometimes, it still loses the data. I am unable to ascertain yet as to when the data gets lost. However, I noticed that the webservice is called with empty parameters when column is sorted and hence the data becomes empty. I didnt think that when you sort on a column, it would invoke the webservice!
Is there any change in the way a portlet behaves based on how it is invoked? Meaning, we can use the PUSB+XPU or do a JS window.open with the URL specified.
I am doing the latter because the User must not see the Browser Nav Bar, Tool Bar etc. so as to hide the Parameters. I could not find a way to set the properties of a window that opens from PUSB + XPU.
I have changed the scope back to session for all Reports.
What I will try now is to use the PUSB + XPU and use JS in the Target portlets to change the properties of the window.
Hi Raj. Our Global Support informed me that you have raised a Support Incident on this issue which is quite reasonable. Let’s follow-up with this issue via the Incident.