Sink JSF 2.0复合组件事件在父页面Backing Bean中 [英] Sink JSF 2.0 Composite Component Event in Parent Page Backing Bean
问题描述
提前感谢协助。 / p>
Peace。
Chris
我发现一种方法可以使用复合组件+自定义组件类型+ ActionSource2 +系统事件。
在你的组合的界面中设置一个组件类型(当不确定时,实现(Mojarra或MyFaces)使用默认组件类型。
< cc:interface componentType =example.Login>
< cc:attribute name =texttype =java.lang.String/>
< cc:attribute name =actionExpressionmethod-signature =void method()/>
< / cc:interface>
< cc:implementation>
< p>
< h:outputLabel value =User/>
< h:inputText id =user/>
< / p>
< p&g t;
< h:outputLabel value =密码/>
< h:inputSecret id =password/>
< / p>
< / cc:implementation>
此组件类型是实现NamingContainer的一个java类(UINamingContainer是实现此接口的组件的子类) 。接下来,您必须实施ActionSource2,以便在用户验证时可以生成一个操作事件。
验证必须在用户和密码组件被验证之后(而不是您的验证但JSF过程验证)。为了知道何时发生验证,我们使用系统事件。
这是自定义组件的代码示例。该类实现了ActionSource2接口的方法,并覆盖了广播来处理ActionEvent。我在Mojarra中使用一些特定的类(因为ActionSource和ActionSource2之间的遗留)。
@FacesComponent(example.Login) //组合中的组件类型
@ListenerFor(systemEventClass = PostValidateEvent.class)//侦听用户和密码验证的事件
public class LoginComponent扩展UINamingContainer实现ActionSource2 {
@Override
public void processEvent(ComponentSystemEvent event)throws AbortProcessingException {
if(event instanceof PostValidateEvent){
System.out.println(post validate);
}
super.processEvent(event);
String user =(String)((HtmlInputText)findComponent(user))。getValue();
String password =(String)((HtmlInputSecret)findComponent(password))。getValue();
System.out.println(user:+ user);
System.out.println(password:+ password);
//一个简单的验证逻辑
if(user!= null&& user.equals(victor)&& password!= null&& password.equals )){
System.out.println(user ok);
queueEvent(new ActionEvent(this));
}
}
private MethodExpression exp;
@Override
public MethodExpression getActionExpression(){
return exp;
}
@Override
public void setActionExpression(MethodExpression action){
exp = action;
}
@Override
public MethodBinding getAction(){
return exp!= null?新的MethodBindingMethodExpressionAdapter(exp):null;
}
@Override
public void setAction(MethodBinding action){
setActionExpression(new MethodExpressionMethodBindingAdapter(action));
}
private MethodBinding actionListener;
@Override
public MethodBinding getActionListener(){
return actionListener;
}
@Override
public void setActionListener(MethodBinding actionListener){
this.actionListener = actionListener;
}
private boolean i;
@Override
public boolean isImmediate(){
return i;
}
@Override
public void setImmediate(boolean immediate){
this.i = immediate;
}
列表< ActionListener> listeners = new LinkedList< ActionListener>();
@Override
public void addActionListener(ActionListener listener){
listeners.add(listener);
}
@Override
public ActionListener [] getActionListeners(){
return listeners.toArray(new ActionListener [0]);
}
@Override
public void removeActionListener(ActionListener listener){
listeners.remove(listener);
}
@Override
public void broadcast(FacesEvent event)throws AbortProcessingException {
super.broadcast(event);
if(Event instanceof ActionEvent){
FacesContext context = getFacesContext();
MethodBinding binding = getActionListener();
if(binding!= null){
binding.invoke(context,new Object [] {event});
}
ActionListener listener = context.getApplication()。getActionListener();
if(listener!= null){
listener.processAction((ActionEvent)event);
}
}
}
}
这是使用页面中的代码:
< ez:login actionExpression =#{bean.logged }/>
I have a conceptual mind-block around the use of a JSF 2.0 composite component within a parent page. I understand how to implement an ActionListener (and others) for a composite component's action but how is this wired-up for the parental page to consume? For example, I want my login composite component to perform authentication and when complete, inform the parent page's backing bean through the an event (ActionListener?) to do some UI initialization work. The key here is the login component would say, "Hey, I'm done and the user is good. Your turn."
Thanks in advance for the assistance.
Peace.
Chris
One way I found you can acomplish this is using composite component + custom component type + ActionSource2 + system events.
In the interface of your composite set a component-type (when not definied, the implementation (Mojarra or MyFaces) uses a default component type.
<cc:interface componentType="example.Login">
<cc:attribute name="text" type="java.lang.String"/>
<cc:attribute name="actionExpression" method-signature="void method()"/>
</cc:interface>
<cc:implementation>
<p>
<h:outputLabel value="User"/>
<h:inputText id="user"/>
</p>
<p>
<h:outputLabel value="Password"/>
<h:inputSecret id="password"/>
</p>
</cc:implementation>
This component type is a java class that implements NamingContainer (UINamingContainer is a subclass of component implementing this interface). Next you have to implement ActionSource2 so you could generate an action event when the user is verified.
The verifyng must be after the user and password components have been validated (not your verification but JSF PROCESS VALIDATIONS). In order to know when the validation has occurs, we use System Events.
This is an example of the code for the custom component. The class implements the methods of the ActionSource2 interface and overrides broadcast to handle ActionEvent's. I use some specific classes in Mojarra (because the legacy between ActionSource and ActionSource2).
@FacesComponent("example.Login") //Component type in the composite
@ListenerFor(systemEventClass=PostValidateEvent.class) //Event to listen for user and password verification
public class LoginComponent extends UINamingContainer implements ActionSource2{
@Override
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
if(event instanceof PostValidateEvent){
System.out.println("post validate");
}
super.processEvent(event);
String user=(String) ((HtmlInputText)findComponent("user")).getValue();
String password=(String) ((HtmlInputSecret)findComponent("password")).getValue();
System.out.println("user: "+user);
System.out.println("password: "+password);
//a simple logic for verification
if(user != null && user.equals("victor") && password != null && password.equals(user)){
System.out.println("user ok");
queueEvent(new ActionEvent(this));
}
}
private MethodExpression exp;
@Override
public MethodExpression getActionExpression() {
return exp;
}
@Override
public void setActionExpression(MethodExpression action) {
exp=action;
}
@Override
public MethodBinding getAction() {
return exp != null ? new MethodBindingMethodExpressionAdapter(exp): null;
}
@Override
public void setAction(MethodBinding action) {
setActionExpression(new MethodExpressionMethodBindingAdapter(action));
}
private MethodBinding actionListener;
@Override
public MethodBinding getActionListener() {
return actionListener;
}
@Override
public void setActionListener(MethodBinding actionListener) {
this.actionListener=actionListener;
}
private boolean i;
@Override
public boolean isImmediate() {
return i;
}
@Override
public void setImmediate(boolean immediate) {
this.i=immediate;
}
List<ActionListener> listeners=new LinkedList<ActionListener>();
@Override
public void addActionListener(ActionListener listener) {
listeners.add(listener);
}
@Override
public ActionListener[] getActionListeners() {
return listeners.toArray(new ActionListener[0]);
}
@Override
public void removeActionListener(ActionListener listener) {
listeners.remove(listener);
}
@Override
public void broadcast(FacesEvent event) throws AbortProcessingException {
super.broadcast(event);
if (event instanceof ActionEvent) {
FacesContext context = getFacesContext();
MethodBinding binding = getActionListener();
if (binding != null) {
binding.invoke(context, new Object[] { event });
}
ActionListener listener = context.getApplication().getActionListener();
if (listener != null) {
listener.processAction((ActionEvent) event);
}
}
}
}
And this is the code in the using page:
<ez:login actionExpression="#{bean.logged}"/>
这篇关于Sink JSF 2.0复合组件事件在父页面Backing Bean中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!