I can't figure out the problem. In listener part of ajax, it gives me the listener reference not found. I don't know what I am doing wrong. I'm working on Oracle JDeveloper IDE. Here is my code.
Here is part of my JSF page:
<af:menuBar id="menuBar">
<af:menu text="Add" id="m1">
<af:commandMenuItem text="Text Box" id="addTextBox" >
<f:ajax event="click" render="msg" listener="#{addItem.start}"/>
</af:commandMenuItem>
</af:menu>
<af:menu text="Contact" id="m2"/>
</af:menuBar>
<af:message id="msg" message="#{addItem.text}" >
Here is my AddItems.java file:
import javax.faces.bean.ManagedBean;
import javax.faces.event.AjaxBehaviorEvent;
#ManagedBean(name="addItem")
public class AddItems {
public AddItems() {
}
String text = "first";
public void start(AjaxBehaviorEvent event) throws javax.faces.event.AbortProcessingException {
setText("changed");
}
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
Related
Problem:After the ActionEvent is triggered (selecting an account), the comboBox is null. When I run the program, I can see that the ComboBox is populated. I think I'm doing something wrong with the FXML loader. I read through the following document: https://openjfx.io/javadoc/12/javafx.fxml/javafx/fxml/doc-files/introduction_to_fxml.html#controllers
While thrilling (actually learned a lot), the document did not give me an answer to my problem. Please advise.... Referring me to another source for further education would be appreciated. If you need more information to answer the question, let me know.
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.ComboBox.setItems(javafx.collections.ObservableList)" because "this.accountComboBox" is null at application.budget/application.budget.Controller.initialize(Controller.java:67)
Line 67 is: accountComboBox.setItems(accountlist);
package application.budget;
import datamodel.Account;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import java.io.IOException;
import java.text.NumberFormat;
public class Controller {
public Button detacctinfo;
private Stage stage;
private Scene scene;
private Parent root;
#FXML
private Button createnewacct, Submit;
#FXML
private AnchorPane mainPanel;
#FXML
private ComboBox<Account> accountComboBox;
#FXML
Label acctbalField = new Label();
private NumberFormat fmt;
public void initialize () {
ObservableList<Account> accountlist = FXCollections.observableArrayList();
accountlist.add(new Account("Bank of America", 10010101.32));
accountlist.add(new Account("Prosperity Bank", 10010101.32));
//ComboBox<Account> selectacct = new ComboBox<>();
// Use a StringConverter to configure our ComboBox to display only the film's title
/* accountComboBox.setConverter(new StringConverter<Account>() {
#Override
public String toString(Account account) {
return account.getAccountName();
}
#Override
public Account fromString(String string) {
return accountComboBox.getItems().stream().filter(ap ->
ap.getAccountName().equals(string)).findFirst().orElse(null);
}
});*/
// Finally, set our ComboBox's items to our sample list
accountComboBox.setItems(accountlist);
System.out.println(accountlist);
}
public void OnItemSelected(ActionEvent e ) throws IOException {
root = FXMLLoader.load(getClass().getResource("AccountHome.fxml"));
Stage window = (Stage) Submit.getScene().getWindow();
window.setScene(new Scene(root));
}
}
package datamodel;
public class Account {
private String accountName;
private Double accountBalance;
public Account(String accountName, Double accountBalance) {
this.accountName = accountName;
this.accountBalance = accountBalance;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Double getAccountBalance() {
return accountBalance;
}
public void setAccountBalance(Double accountBalance) {
this.accountBalance = accountBalance;
}
#Override //Esto dice que cuando un variable se usa, va a dar el valor de abajo
public String toString() {
return accountName;
}
public String getBalance() {
return String.valueOf(accountBalance);
}
}
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.ComboBox.setItems(javafx.collections.ObservableList)" because "this.accountComboBox" is null
at application.budget/application.budget.Controller.initialize(Controller.java:67)
Line 67 is: accountComboBox.setItems(accountlist);
After some research, it seems like each FXML document needs it's own controller. Been doing this for about 2 weeks. Excuse the lack of education on my part.
I created a Panel in which Im trying to get live Ajax behaviour to some radio options.
The problem is that I can not set the current active option, in the setter "setSelectedLang", the parameter there is always null, even when I click on different radio options. How can that be fixed?
I am running Wicket version 7.5.0.
package xx.yy.admin
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.RadioChoice;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.model.PropertyModel;
import xx.yy.admin.Survey;
import xx.yy.admin.AjaxListener;
import java.util.Arrays;
import java.util.List;
public class LanguageSelectionPanel extends GenericPanel<Void> {
private static final String SVENSKA = "Sve";
private static final String ENGELSKA = "Eng";
private AjaxListener listener;
private Form<Void> form;
private List<String> languages = Arrays.asList(SVENSKA, ENGELSKA);
private Survey surveyModel;
private String selectedLang = "Sve";
private RadioChoice languageRadioChoice;
public SurveyLanguageSelectionPanel(String id, Survey survey, AjaxListener listener) {
super(id);
this.surveyModel = survey;
this.listener = listener;
initialize();
}
protected void initialize() {
super.onInitialize();
form = new Form<Void>("langform") {
#Override
protected void onSubmit() {
info("Init : ");
}
};
add(form);
languageRadioChoice = getLanguageSelection();
form.add(languageRadioChoice);
}
private RadioChoice getLanguageSelection() {
RadioChoice<String> langRadioChoice = new RadioChoice<>("languages",
new PropertyModel<>(this, "selectedLang"), languages);
// Add Ajax Behaviour...
langRadioChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
protected void onUpdate(AjaxRequestTarget target) {
listener.onUpdate(target);
}
});
return langRadioChoice;
}
public void setSelectedLang(String selectedLang) {
this.selectedLang = selectedLang;
}
public String getSelectedLang() {
return selectedLang;
}
}
The html code:
<body>
<wicket:panel>
<form style="" class="" wicket:id="langform">
<wicket:enclosure child="languages">
<span wicket:id="languages"></span>
</wicket:enclosure>
<br/>
<hr/>
</form>
</wicket:panel>
</body>
</html>
You have to use "AjaxFormChoiceComponentUpdatingBehavior" as described here:
onchange get current value with radioChoice
i.e.
langRadioChoice.add(new AjaxFormChoiceComponentUpdatingBehavior() {
protected void onUpdate(AjaxRequestTarget target) {
listener.onUpdate(target);
}
});
I've a dataTable within a dataTable. The initial dataTable has a list of components that appear on the page. One of these components will be a list of strings which can have elements added or deleted. When I change a string in this list, I expect the value to show up in the bean and it is not.
Below I have an example of my problem. The page renders a text input field for the first component then three text input fields to represent the second component which is a list of three input fields.
I have valueChange listener on all the input fields. The listener, is in the InnerBean class, prints out the source and the value that changed.
For the standalone input field, the listener correctly prints out the changed value and shows that the bean has been updated with this value. For any of the input fields from the list, the listener prints out the previous value of the input field and the bean has not been updated. On the ajax update of the inner datatable, the changed value is replace with the original value.
Since the valueChange listener is called, it appears that Primefaces knows that the value has changed. The code just doesn't seem to record the changed value.
Any help is appreciated.
I'm using Primefaces 8.0 and JSF 2.2.20.
Here is the xhtml:
<p:panel id="testPanel" header="#{myController.outerBean.name}" toggleable="true" collapsed="false" >
<p:dataTable id="testTable" value="#{myController.outerBean.innerBeanList}" var="bean">
<p:column >
<!-- TEXT COMPONENT-->
<h:panelGroup rendered="#{bean.type eq 'text'}" >
<p:inputText id="textfield" value="#{bean.value}" style="width:100%;" >
<p:ajax event="valueChange" listener="#{bean.textListListener}" update="testTable" />
</p:inputText>
</h:panelGroup>
<!-- LIST COMPONENT -->
<h:panelGroup rendered="#{bean.type eq 'textlist'}" >
<p:dataTable id="testListTable" styleClass="datatableWithoutBorder" style="width:320px"
var="textAddition" value="#{bean.list}" rowIndexVar="rowIndex" >
<p:column >
<p:inputText id="textAdd" value="#{textAddition}" style="width: 100%;">
<p:ajax event="valueChange" listener="#{bean.textListListener}" update="testListTable"/>
</p:inputText>
</p:column>
</p:dataTable>
</h:panelGroup>
</p:column>
</p:dataTable>
<h:panelGrid columns="1" style="width:100%;">
<h:panelGroup style="float:right">
<p:commandButton id="submitBtn" value="Submit"
action="#{dummyController.submit}"
update="messages #this"
icon="fa fa-save"/>
</h:panelGroup>
</h:panelGrid>
</p:panel>
My controller code:
public class MyController {
private OuterBean outerBean;
public MyController() {
System.out.println("MyController instantiated");
setOuterBean(new OuterBean());
}
public void submit() {
for (InnerBean ab: outerBean.getInnerBeanList()) {
System.out.println(ab.getLabel() + ": " + ab.getValue() + ":" + ab.getList() );
}
}
public void clear() {
// TODO
}
// Getter/Setter methods
public OuterBean getOuterBean() {
return outerBean;
}
public void setOuterBean(OuterBean outerBean) {
this.outerBean = outerBean;
}
}
My OuterBean with the list of components:
public class OuterBean implements Serializable {
private String name;
private String value;
private List<InnerBean> innerBeanList;
public OuterBean() {
name = "Entry Panel #1";
value = "";
innerBeanList = new ArrayList<InnerBean>();
InnerBean ab1 = new InnerBean();
ab1.setLabel("First Component");
ab1.setType("text");
ab1.setValue("Input text");
innerBeanList.add(ab1);
InnerBean ab2 = new InnerBean();
ab2.setLabel("Second Component");
ab2.setType("textlist");
ArrayList<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");
ab2.setList(list);
innerBeanList.add(ab2);
}
//
// Getter/Setters
//
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public List<InnerBean> getInnerBeanList() {
return innerBeanList;
}
public void setInnerBeanList(List<InnerBean> innerBeanList) {
this.innerBeanList = innerBeanList;
}
}
My InnerBean which represents a component to be render. One of which can be a list of strings:
public class InnerBean implements Serializable {
// Type of component
public static final String TEXT = "text";
public static final String TEXTLIST = "textlist";
private String label;
private String type; // If TEXT, use value; if TEXTLIST, use list.
private String value;
private List<String> list = new ArrayList<String>();
public InnerBean() {
}
public void textListListener(AjaxBehaviorEvent event) {
System.out.println("Listener called");
System.out.println(" Source: " + event.getSource().toString());
System.out.println(" Value: " + ((UIInput)event.getSource()).getValue());
System.out.println(" List: " + list.toString());
System.out.println(" Event: " + event.toString());
}
//
// Setters and getters
//
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
I do have a page, where I have a list of rich:collapsiblePanel that hold input elements. These collapsiblePanels themselves store their expanded/collapsed state within a backing bean.
Now I have the use case to Open/Close all of these collapsiblePanels at once, with one mouse click. So I have tried to achieve this with the two commandButtons over the list. These use the attached actionListener to iterate over all backing beans of the collapsiblePanels and set the expanded flag to true/false.
This seems to work, unless you Open or Close one of the collapsiblePanels on their own. As soon as that happens clicking the buttons does not do anything anymore.
<h:form prependId="false">
<a4j:commandButton value="Open All" actionListener="#{viewBean.doOpenAll}" render="c" />
<a4j:commandButton value="Close All" actionListener="#{viewBean.doCloseAll}" render="c" style="margin-left: 10px;" />
<a4j:outputPanel id="c">
<a4j:repeat id="repeat" value="#{viewBean.items}" var="item">
<rich:collapsiblePanel id="panel" expanded="#{item.expanded}">
<h:outputLabel id="text_lbl" value="text" />
<h:inputText id="text" value="#{item.text}" />
</rich:collapsiblePanel>
</a4j:repeat>
</a4j:outputPanel>
</h:form>
I have published a project on github so that you can try around with the code.
For completeness here are the two backing beans
#ViewScoped
#ManagedBean
public class ViewBean implements Serializable {
static final Logger LOG = LoggerFactory.getLogger(ViewBean.class);
private static final long serialVersionUID = -6239437588285327644L;
private List<ListItem> items;
public ViewBean() {
items = new ArrayList<ListItem>(10);
for (int i = 0; i < 10; i++) {
items.add(new ListItem("item " + i));
}
}
public void doOpenAll() {
LOG.debug("open all");
for (ListItem item : items) {
item.setExpanded(true);
}
}
public void doCloseAll() {
LOG.debug("close all");
for (ListItem item : items) {
item.setExpanded(false);
}
}
public List<ListItem> getItems() {
return items;
}
}
public class ListItem {
private boolean expanded;
private String text;
public ListItem(String text) {
super();
this.text = text;
}
public boolean isExpanded() {
return expanded;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
This may be related to this RichFaces bug?!: https://issues.jboss.org/browse/RF-11546
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}"/>