Details
-
Type: New Feature
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: 1.7DR#2
-
Component/s: ICE-Components
-
Labels:None
-
Environment:All
-
Affects:Documentation (User Guide, Ref. Guide, etc.), Sample App./Tutorial
Description
[Q#] blocks represent questions that have to be investigated
Right now, if you use a menuPopup with MenuItem actionListener, you can't tell which component was clicked on. We need a means of passing that information back to the server, where application level code see what summoned the popup, and hence, on what to do the actions.
At the minimum, we need the clientId of the summoner component, and if a bean method can be invoked while UIData/UISeries iteration has arrived at that summoner component, then all of the current row / column relationships should be properly setup, when that bean method is invoked, to know exactly what context the application needs to do its action. [Q1] Assuming that all of our container components are UISeries components, encode their row information in their children's clientIds. Investigate: panelSeries, dataTable, etc. [/Q1] [Q2] It should be possible to use a simple ValueBinding bean property setter, invoked in the UPDATE_MODEL phase, since I think that iteration happens then too [/Q2] The ValueBinding property, called menuContext, would have to be on the summoner component, since the menuPopup won't necessarily be near it in the component tree, so it might have different UISeries iteration. It would set a reference to the summoner UIComponent itself, which applications should not keep beyond the life of that setter method's execution. As well, any intra-component context info could be set as well, such as selectInputDate setting which specific date was context-clicked on. This would have to be passed in, from the Javascript, to the request map, along with the summoner clientId.
The summoner clientId will have to be setup to go to the server when the onContextClick event is caught, but it will only be transmitted if one of the MenuItems has been clicked. So if the menu is closed without anything being clicked, that clientId should be discarded, so it's not sent when some other non-menuPopup submit occurs.
The problem with the simple solution above is that it will probably require component bindings in the bean, to query the UISeries what their current row is. Bindings cause problems in Seam, and it's generally preferred to do a POJO approach. In that light, it's advantageous to be able to directly pass to the bean the row information directly, so it doesn't have to go to the components, but can just directly access the data models, and extract the info from there.
Now, the clientIds technically hold that information already, but each container can encode their row information differently, so it would be their responsibility to decode that information as well. Just like how the summoner component and its intra-component context was set, the containers could also set themselves and their row information into the bean.
[IF Q1]
In the DECODE phase the containers can examine the summoner clientId in the request map, and derive their row from there, for setting in the UPDATE_MODEL phase.
[ELSE]
If the clientIds don't contain all of the information already, and we're not relying on component bindings, then we have to make it so that the onContextClick event will bubble up all of the way, except that while the first receiver of the event, the summoner, will make the menuPopup show, the others higher up the tree will simply save their clientIds and row information for the upcoming submit, along with where the summoner saved its clientId and intra-component context.
[ENDIF]
Since there are several components all calling setters on the bean, one after the other, with references to themselves, and any row indexes, or intra-component context, there should be some standard wrapper object that would encapsulate that, along with a terminal boolean to tell the bean that it's finally gotten the setter for the actual summoner, and not just a parent container.
Right now, if you use a menuPopup with MenuItem actionListener, you can't tell which component was clicked on. We need a means of passing that information back to the server, where application level code see what summoned the popup, and hence, on what to do the actions.
At the minimum, we need the clientId of the summoner component, and if a bean method can be invoked while UIData/UISeries iteration has arrived at that summoner component, then all of the current row / column relationships should be properly setup, when that bean method is invoked, to know exactly what context the application needs to do its action. [Q1] Assuming that all of our container components are UISeries components, encode their row information in their children's clientIds. Investigate: panelSeries, dataTable, etc. [/Q1] [Q2] It should be possible to use a simple ValueBinding bean property setter, invoked in the UPDATE_MODEL phase, since I think that iteration happens then too [/Q2] The ValueBinding property, called menuContext, would have to be on the summoner component, since the menuPopup won't necessarily be near it in the component tree, so it might have different UISeries iteration. It would set a reference to the summoner UIComponent itself, which applications should not keep beyond the life of that setter method's execution. As well, any intra-component context info could be set as well, such as selectInputDate setting which specific date was context-clicked on. This would have to be passed in, from the Javascript, to the request map, along with the summoner clientId.
The summoner clientId will have to be setup to go to the server when the onContextClick event is caught, but it will only be transmitted if one of the MenuItems has been clicked. So if the menu is closed without anything being clicked, that clientId should be discarded, so it's not sent when some other non-menuPopup submit occurs.
The problem with the simple solution above is that it will probably require component bindings in the bean, to query the UISeries what their current row is. Bindings cause problems in Seam, and it's generally preferred to do a POJO approach. In that light, it's advantageous to be able to directly pass to the bean the row information directly, so it doesn't have to go to the components, but can just directly access the data models, and extract the info from there.
Now, the clientIds technically hold that information already, but each container can encode their row information differently, so it would be their responsibility to decode that information as well. Just like how the summoner component and its intra-component context was set, the containers could also set themselves and their row information into the bean.
[IF Q1]
In the DECODE phase the containers can examine the summoner clientId in the request map, and derive their row from there, for setting in the UPDATE_MODEL phase.
[ELSE]
If the clientIds don't contain all of the information already, and we're not relying on component bindings, then we have to make it so that the onContextClick event will bubble up all of the way, except that while the first receiver of the event, the summoner, will make the menuPopup show, the others higher up the tree will simply save their clientIds and row information for the upcoming submit, along with where the summoner saved its clientId and intra-component context.
[ENDIF]
Since there are several components all calling setters on the bean, one after the other, with references to themselves, and any row indexes, or intra-component context, there should be some standard wrapper object that would encapsulate that, along with a terminal boolean to tell the bean that it's finally gotten the setter for the actual summoner, and not just a parent container.
Please provide sample code showing usage of the menuPopup.