add event in dynamic component created in the bean jsf - jsf

Good day, so guys, what I'm wanting to do is the following, I add a HtmlSelectOneMenu via bean in JSF page, and like it when the guy changed his value, HtmlSelectOneMenu him to add another, add the HtmlSelectOneMenu'm getting no problem, however like to know how do I add an event to them via BEAN course ehehee
HtmlSelectOneMenu select = new HtmlSelectOneMenu();
HtmlOutputLabel lblData = new HtmlOutputLabel();
lblData.setValue(list.get(contador).getItem().getNome());
UISelectItem item = new UISelectItem();
item.setItemLabel("NÃO");
item.setItemValue(false);
UISelectItem item2 = new UISelectItem();
item2.setItemLabel("SIM");
item2.setItemValue(true);
select.getChildren().add(item);
select.getChildren().add(item2);
FacesContext context = FacesContext.getCurrentInstance();
ELContext elContext = context.getELContext();
Application app = context.getApplication();
ExpressionFactory expressionFactory = app.getExpressionFactory();
ValueExpression ve = expressionFactory.createValueExpression(elContext, "#{projetoBean.qualRespondeu}", String.class);
select.setValueExpression("valeu", ve);
UIPanel container = (UIPanel) FacesContext.getCurrentInstance().getViewRoot().findComponent(":formProjeto:painel");
container.getChildren().add(lblData);
container.getChildren().add(select);
contador++;

Thanks for answers Kolossus however, decided as follows:
AjaxBehavior ajax = new AjaxBehavior();
ajax.setAsync(true);
ajax.setUpdate(":formProjeto");
MethodExpression ex = expressionFactory.createMethodExpression(elContext, "#{projetoBean.adicionaPergunta()}", null, new Class[]{});
ajax.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl(ex, ex));
select.addClientBehavior("change", ajax);

Try the following steps:
Create the AjaxBehaviorListener (the actual processing of the event):
MyAjaxBehaviorListener implements AjaxBehaviorListener{
#Override
public void processAjaxBehavior(AjaxBehaviorEvent e) throws AbortProcessingException {
//perform the event processing here
}
}
Attach the listener to an AjaxBehavior
AjaxBehavior ajaxBehavior = (AjaxBehavior) FacesContext.getCurrentInstance().getApplication() .createBehavior(AjaxBehavior.BEHAVIOR_ID);
MyAjaxBehaviorListener listener = new MyAjaxBehaviorListener();
ajaxBehavior.setExecute(Collections.singletonList("#this")); //sets the execute attribute of the event handler
ajaxBehavior.addAjaxBehaviorListener(listener);
Attach the AjaxBehavior to the component
item.addClientBehavior("change",ajaxBehavior); //set the triggering event to "change"

Related

How to generate primefaces PickList component programmatically?

public void populateForm(ComponentSystemEvent event) {
HtmlForm form = (HtmlForm) event.getComponent();
List<String> citiesSource = new ArrayList<String>();
List<String> citiesTarget = new ArrayList<String>();
citiesSource.add("San Francisco");
citiesSource.add("London");
citiesSource.add("Paris");
citiesSource.add("Istanbul");
citiesSource.add("Berlin");
citiesSource.add("Barcelona");
citiesSource.add("Rome");
cities = new DualListModel<String>(citiesSource, citiesTarget);
PickList pickList = new PickList();
pickList.setId("pickList");
pickList.setValue(cities);
pickList.setVar("cities");
pickList.setItemLabel(pickList.getVar());
pickList.setItemValue(cities);
form.getChildren().add(pickList);
}
This was my approach, and output I got is:
But if I add <p:pickList id="pickList" value="#{bean.cities}" var="cities" itemLabel="#{cities}" itemValue="#{cities}" /> in my xhtml, I get this output:
What is going on here?
This is how I solved the PickList issue:
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory ef = context.getApplication().getExpressionFactory();
PickList pickList = new PickList();
ValueExpression pickListValue = ef.createValueExpression(
context.getELContext(), "#{ruleManagedBean.cities}",DualListModel.class);
ValueExpression pickListVar = ef.createValueExpression(
context.getELContext(), "cities", String.class);
ValueExpression pickListItemLabel = ef.createValueExpression(
context.getELContext(), "#{cities}", String.class);
ValueExpression pickListItemValue = ef.createValueExpression(
context.getELContext(), "#{cities}", String.class);
pickList.setId("pickList");
pickList.setValueExpression("value", pickListValue);
pickList.setValueExpression("var", pickListVar);
pickList.setValueExpression("itemLabel", pickListItemLabel);
pickList.setValueExpression("itemValue", pickListItemValue);
form.getChildren().add(pickList);
Note: ruleManagedBean.cities refers to the DualListModel, populated as
List<String> citiesSource = new ArrayList<String>();
List<String> citiesTarget = new ArrayList<String>();
citiesSource.add("San Francisco");
citiesSource.add("London");
citiesSource.add("Paris");
citiesSource.add("Istanbul");
citiesSource.add("Berlin");
citiesSource.add("Barcelona");
citiesSource.add("Rome");
cities.setSource(citiesSource);
cities.setTarget(citiesTarget);
Make sure that you have declared this DualListModel globally as below and has getter setter methods
private DualListModel<String> cities = new DualListModel<String>();
Instead of PickList pickList = new PickList(); try this:
Application application = FacesContext.getCurrentInstance().getApplication();
PickList pickList = (PickList) application.createComponent(PickList.COMPONENT_TYPE);
Change your pickList.setValue(cities); for this:
Note: cities must be a field on your bean with its own getter.
ExpressionFactory ef = application.getExpressionFactory();
ELContext elc = FacesContext.getCurrentInstance().getELContext();
ValueExpression value = ef.createValueExpression(elc, "#{bean.cities}", DualListModel.class);
pickList.setValueExpression("value", value);

Programmatically created h:commandButton does not invoke onclick="processInput(id)"

Here is how I programmatically create a <h:commandButton>:
private HtmlCommandButton generateButton(String id,String label){
HtmlCommandButton button = (HtmlCommandButton)app.createComponent
(HtmlCommandButton.COMPONENT_TYPE);
button.setId(id);
button.setValue(label);
button.setOnclick("processInput(id)");
return button;
}
When the button is clicked, I need to execute the processInput(id) function. However, when I click that button, nothing happens.
Onclick function will add the processInput as a JavaScript function . You need to pass the id in your Java method like,
setOnClick("processInput(" + id + ")");
To add an action method you need to use setActionExpression,
HtmlCommandButton button = new HtmlCommandButton();
FacesContext fc = FacesContext.getCurrentInstance();
ELContext ctx = fc.getELContext();
String expression = "#{processInput('id')}";
Class[] parameterTypes = new Class[1];
parameterTypes[0]=String.class;
MethodExpression me = fc.getApplication().getExpressionFactory().
createMethodExpression(ctx,
expression, returnType, parameterTypes);
button.setActionExpression(me);
button.setOnclick("alert('');");

How to add SetPropertyActionListener correctly?

i use Primefaces 3.0.1 and build up a menubar with programmatically filled model. I need some Links like depotDetails.xhtml?id=1 But if i use these URL for my menuitem
item.setUrl("depotDetail.xhtml?id=1"); // that dont work
so i tried to add an ActionListener:
FacesContext facesContext = FacesContext.getCurrentInstance();
ValueExpression target = facesContext.getApplication().getExpressionFactory().createValueExpression(FacesContext.getCurrentInstance().getELContext(), "#{DepotBean.currentDepot}",String.class);
ValueExpression value = facesContext.getApplication().getExpressionFactory().createValueExpression(FacesContext.getCurrentInstance().getELContext(), "ehnemeneee",String.class);
ActionListener handler = new SetPropertyActionListenerImpl(target, value);
item.addActionListener(handler);
but that also dont work. Can anybody help?
Greets Thomas
I got a solution ... but is it the right way?
// building the menu model ..
UIParameter param = null;
for(Depots testdepot: depotList){
param = new UIParameter();
param.setName("currentDepotId");
param.setValue(testdepot.getIdDepot());
item = new MenuItem();
item.setValue(testdepot.getDepotName());
// calling menuListener
item.addActionListener(new MenuListener());
item.setUpdate("messages");
item.setId("menuItemDepot"+testdepot.getIdDepot());
item.getChildren().add(param);
submenu.getChildren().add(item);
}
// MenuListener
public void processAction(ActionEvent event) throws AbortProcessingException {
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);
// get param id
String name = (String) event.getComponent().getAttributes().get("currentDepotId");
// set session var
session.setAttribute("currentDepotId", name);
fc.getExternalContext().redirect(request.getContextPath() + "/userarea/depotDetail.xhtml");
}
// read the session in the depot bean
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);
String currentDepotId = session.getAttribute("currentDepotId");

JSF: How to attach an actionListener to component created programatically?

I have to create some commandLinks dynamically and attach some action listener to it, So I've put <h:panelGrid> on the JSP page and used such code to add the commandLinks and to assign action listeners to:
public ManagedBean(){
List<UIComponenet> child = panelGrid.getChilderen();
list.clear();
List<MyClass> myList = getSomeList();
for (MyClass myObj : myList){
FacesContext ctx = FacesContext.getCurrentContext();
HtmlCommandLink cmdLink = (HtmlCommandLink) ctx.getApplication.createComponent(HtmlCommandLink.COMPONENT_TYPE);
cmdLink.setValue(myObj.getName());
cmdLink.setActionLinstner(new ActionListener(){
public void processAction(ActionEvent event) throws AbortProcessingException{
System.out.println (">>>>>>>>>>>>>>>>>I am HERE ");
}
});
child.add(cmdLink);
}
}
But unfortunately, when I press this commandLinks, an exception thrown! How can I add component event listeners at runtime?
(Note, the code above my contain syntax/compilation errors as I just wrote).
First, you need to manually assign ID to any dynamically created UINamingContainer, UIInput and UICommand components. Otherwise JSF can't locate them in the component tree based on the request parameters, because it wouldn't match the autogenerated ID's.
Thus, at least do:
HtmlCommandLink link = new HtmlCommandLink();
link.setId("linkId");
// ...
Second, you're supposed to create an ActionListener as MethodExpression as follows:
FacesContext context = FacesContext.getCurrentInstance();
MethodExpression methodExpression = context.getApplication().getExpressionFactory().createMethodExpression(
context.getELContext(), "#{bean.actionListener}", null, new Class[] { ActionEvent.class });
link.addActionListener(new MethodExpressionActionListener(methodExpression));
// ...
...and of course have the following method in the backing bean class behind #{bean}:
public void actionListener(ActionEvent event) {
// ...
}
All the above dynamic stuff basically does the same as the following raw JSF tag:
<h:commandLink id="linkId" actionListener="#{bean.actionListener}" />
I had the same problem.
Transient components do not work with actionListeners.
Do not call
FacesContext.getCurrentInstance().getViewRoot().setTransient(true);
or
component.setTransient(true);
As soon as I removed it, it was OK.

JSF ResponseWriter custom components

I know about startElement, endElement, and writeAttribute methods on ResponseWriter. My problem is that I want to for example output a h:commandLink by declaring it like HtmlCommandLink link = new HtmlCommandLink(); .
How can I output other UIComponents like this in my own component? I might want to use some RichFaces ajax stuff in my components aswell so hoping I can avoid making it all by scratch.
Edit: What I'm trying to do is create my own tag library with the following tag <myTags:commentTree>. Every comment have a reply button, when the reply button is clicked I render the reply form beneath the comment. Once that is rendered, I would like to output for example the richfaces <a4j:commandButton> component. This have to be done inside my own java tag file which Ive called for CommentsTreeUI.java.
Normally I output all my elements that display the forms and buttons with writer.startElement("input", myComponent); writer.writeAttribute("type", "button", null); but if I could instead do for example startElement("a4j:commandbutton", myComponent) that would help my ALOT since it has all the built in ajax features etc.
Any clues?
This problem was solved by adding new components by using
HtmlCommandButton button = new HtmlCommandButton();
button.encodeAll(context);
You can do something like this:
HtmlCommandLink link = new HtmlCommandLink();
getChildren().add(link);
It does depend on what you want to do with the child components though i.e. if you want them surrounded with custom HTML (in an HTML list, for example) you will need something a bit more complex.
One approach to making composite controls is to use the binding attribute to associate the tag with your own code:
<f:view>
<h:form>
<h:panelGroup binding="#{compositeControlBean.panelGrid}" />
</h:form>
</f:view>
The bean configuration in faces-config.xml:
<managed-bean>
<managed-bean-name>compositeControlBean</managed-bean-name>
<managed-bean-class>
composite.CompositeControlBean
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
The bean code:
/**
* Configure this bean in request scope as "compositeControlBean".
*/
public class CompositeControlBean {
private transient UIComponent panelGrid;
public UIComponent getPanelGrid() {
if (panelGrid == null) {
panelGrid = createCompositePanel();
}
return panelGrid;
}
public void setPanelGrid(UIComponent panelGrid) {
this.panelGrid = panelGrid;
}
private UIComponent createCompositePanel() {
initContextMemebers();
UIComponent commandLink = createCommandLink();
String id = view.createUniqueId();
UIComponent panelGrid = application
.createComponent("javax.faces.HtmlPanelGroup");
panelGrid.setId(id);
panelGrid.setRendererType("javax.faces.Group");
panelGrid.getChildren().add(commandLink);
return panelGrid;
}
private UIComponent createCommandLink() {
// create control
String id = view.createUniqueId();
UIComponent commandLink = application
.createComponent("javax.faces.HtmlCommandLink");
commandLink.setId(id);
commandLink.setRendererType("javax.faces.Link");
// set attributes (bind to printHello method)
Map<String, Object> attributes = commandLink
.getAttributes();
MethodExpression action = expressionFactory
.createMethodExpression(elContext,
"#{compositeControlBean.printHello}",
String.class, new Class<?>[0]);
attributes.put("value", "print hello");
attributes.put("actionExpression", action);
return commandLink;
}
private transient FacesContext context;
private transient Application application;
private transient ELContext elContext;
private transient ExpressionFactory expressionFactory;
private transient UIViewRoot view;
private void initContextMemebers() {
context = FacesContext.getCurrentInstance();
application = context.getApplication();
elContext = context.getELContext();
expressionFactory = application.getExpressionFactory();
view = context.getViewRoot();
}
public String printHello() {
System.out.println("Hello");
return null;
}
}

Resources