Prime faces validation for treeview - java

I´m currently exploring Prime faces, and I´m wondering how we can validate the selection from a treeview? With an for example inputtextarea, this is very simple
<p:inputTextarea id="description"
value="#{createAdd.add.description}" cols="50" rows="5"
validatorMessage="Max length is 25" required="true"
requiredMessage="Description is required">
<f:validateLength maximum="25" />
</p:inputTextarea>
<p:message for="description" />
Here we get valdation for the textinput using the required attribute and the tag. But for the TreeView component there is no required attribute, and the tags does not work.
So, given for example
<p:tree value="#{treeBean.root}" var="node" dynamic="true"
id="category" selectionMode="single"
selection="#{createAdd.add.category}" >
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
How can we validate that one node has actually been selected?

I think validation has to be done in the action method of your submit button.
If I get it right you have two beans for your p:tree: the TreeBean and the CreatAdd bean. I assume your action method is in the CreateAdd bean:
If your submit button looks like this:
<h:commandButton value="#{bundle.del}" action="#{CreateAdd.doSubmitAction}"/>
Then you could check the selected value in the action method:
public String doSubmitAction() {
if(category == null) {
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "No node selected", "No node selected");
FacesContext.getCurrentInstance().addMessage(null, facesMsg);
return null;
}
// do other stuff
}

You can do validation in your backing bean.

Related

JSF list depending on selected value returning nullPointer

In my jsf page, in a dialog, I have a list of EntityB which depends on selected EntityA in a datatable.
When I first load the page it's giving me nullPpointer exception because nothing is selected in the first place. Can anyone tell me how to prevent this?
EDIT: I added an actionlistener to the link who open the dialog
and getting this error:
Cannot convert DemandesDocsAdministratif type DemandesDocsAdministratif to class javax.faces.event.ActionEvent
JSF:
<p:commandLink value="#{demande.idDemandeDocAdministratif}"
oncomplete="PF('dlg2').show()" process="#this"
update=":form:pg" actionListener="#{gestionDemandesMB.fillEntityB}">
<f:setPropertyActionListener
target="#{gestionDemandesMB.SelectedEntityA}" value="#{demande}"
/>
</p:commandLink>
<form>
<datatable>
</datatable>
<p:dialog>
<p:selectOneMenu id="Signataires"
value="#{gestionDemandesMB.entityB}">
<f:selectItems value="#{gestionDemandesMB.listEntityB}"
var="sign" itemLabel="#{sign.libRole}"
itemValue="#{sign.idPoste}" />
</p:selectOneMenu>
</p:dialog>
</form>
Bean:
public List<EntityA> getListEntityB() {
if ( selectedentityA != null ){
return entityBService.ListByentityA(selectedEntityA)
; } else {
return Collections.emptyList() ; }
Bean listener that I'm working with now:
public void fillSignataires(ActionEvent event)
{
listB = entityBService.ListByentityA(selectedEntityA)
signaRender = true ;
}
this is the getter of entity B list, I'm looking for a way to either get an empty list or call only when I open dialog.
You could use rendered="#{not empty bean.list}" to prevent the rendering of the selectOnMenu until you have the object filled.
You can also add a f:selectItem with a "Select" label and empty itemValue such as itemValue = " ". By the way, never have a null list, list shouldn't be null but it can be empty. It's the best practice. So you can initialize your listEntityB as an empty list at post construct of your bean.
<p:selectOneMenu id="Signataires"
value="#{gestionDemandesMB.entityB}">
<f:selectItem itemLabel="Select" itemValue="" />
var="sign" itemLabel="#{sign.libRole}"
<f:selectItems value="#{gestionDemandesMB.listEntityB}"
var="sign" itemLabel="#{sign.libRole}"
itemValue="#{sign.idPoste}" />
</p:selectOneMenu>

Tips on how to use <rich:notifyMessage>

I have a page to search for authors. It should show the information about the found author or show a message when the author is not found.
I'm trying to use <rich:notifyMessage>, but the problem is that when I use it, the results from the found authors don't appear and, also, the message appear on the right up corner of the page and I'd like it to appear bellow the panel, where the search results would appear.
Look at how I'm doing that, is there a better way to do it?
xhtml
<h:form>
<br />
<br />
Insert Author
<br />
<br />
<br />
<rich:panel id="panel" style="width:310px">
<f:facet name="header">Search for the author you want to insert</f:facet>
<h:panelGrid columns="3">
Name: <h:inputText value="#{insertAuthorController.nameToSearch}" />
<a4j:commandButton value="Search" action="#{insertAuthorController.searchAuthor()}">
</a4j:commandButton>
</h:panelGrid>
</rich:panel>
<br />
<rich:notifyMessage/>
<rich:dataTable value="#{insertAuthorController.authorListOfMap}" var="result">
<c:forEach items="#{insertAuthorController.variableNames}" var="vname">
<rich:column>
<f:facet name="header">#{vname}</f:facet>
#{result[vname]}
</rich:column>
</c:forEach>
</rich:dataTable>
<br />
<h:commandButton value="Go to insert page" action="#{insertAuthorController.searchAuthor()}" />
</h:form>
Bean
public void searchAuthor() {
this.variableNames.clear();
List<String> uris = new ArrayList<String>();
uris = this.authMapper.searchAuthorUriByName(this.nameToSearch);
if( (uris != null) && (!uris.isEmpty()) ) {
for( String uri : uris ) {
Map<String, String> map = new HashMap<String, String>();
String name = this.authMapper.searchNameByAuthorUri(uri);
String email = this.authMapper.searchEmailByAuthorUri(uri);
map.put("URI", uri);
map.put("Nome", name);
map.put("Email", email);
authorListOfMap.add(map);
}
this.addVariableNames();
} else {
FacesContext ctx = FacesContext.getCurrentInstance();
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,"Detail","Author not found!"); //FacesMessage has other info levels
ctx.addMessage(null,msg);
}
}
Thank you!
The notifyMessage is supposed to behave like that (i.e. pop up in the corner of the screen), if you want just a simple text message use <rich:message>.
Or in this simple case you can check if the result returned something:
<h:outputText value="No results"
rendered="#{fn:length(insertAuthorController.authorListOfMap) == 0}">
Your table doesn't show up because you need to rerender it if you want to see the changes:
<rich:dataTable id="authorsTable" …>
<a4j:commandButton … render="authorsTable" />

JF2 Dynamic form element doesn't remember input and page refreshes every time I add element

I am trying to make a form with options to add rows. However, after I type in some input and click the add button again, the input I enter disappears. I'm not sure what is wrong with my code. In addition, when I click the add button, the page refreshes. Is there way to stop this page refresh?
Person.java
public class Person{
private List<String> guys = new ArrayList<String>();
public List<String> getGuys() {
return guys;
}
public void setGuys(List<String> guys) {
this.guys = guys;
public void addNewItem(){
guys.add("");
}
}
form.xhtml
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Guys: " />
<h:dataTable value="#{person.guys}" var="men">
<h:column>
<p:inputText value="#{men}" />
</h:column>
</h:dataTable>
<h:commandButton name="add" value="Add" action="#{person.addNewItem}" />
</h:panelGrid>
<br />
<h:commandButton name="submit" type="submit" value="Submit"></h:commandButton>
</h:form>
Provided that the bean is placed in the right scope for the functional requirement, the view scope, the only major mistake left is that you're expecting that the String class has some magic setter method.
It hasn't. The String class is immutable. The following will never work on a String:
<p:inputText value="#{men}" />
You have 2 options:
Create a real model class. You can find complete examples in the following answers:
How to dynamically add JSF components
Recommended JSF 2.0 CRUD frameworks
Set the value by row index instead:
<h:dataTable binding="#{table}" value="#{person.guys}">
<h:column>
<p:inputText value="#{person.guys[table.rowIndex]}" />
</h:column>
</h:dataTable>
(note: no additional bean property necessary for the table! the code is as-is)
This does basically a person.getGuys().add(table.getRowIndex(), submittedValue). I.e. the setter is invoked on the List itself, which works perfectly fine. See also the following related answers concerning ui:repeat:
Using <ui:repeat><h:inputText> on a List<String> doesn't update model values
How map multiple inputText to an array property?
You never update your list, you are just adding empty items. You should do something like this:
Person.java (viewscoped)
public class Person implements Serializable {
private List<String> guys = new ArrayList<String>();
private HtmlDataTable dtGuys;
public void addNewItem() {
guys.add("");
}
public void addToList(ValueChangeEvent e) {
guys.set(dtGuys.getRowIndex(), e.getNewValue().toString());
}
public String save() {
System.out.println("saving...");
for (String item : guys) {
System.out.println("item= " + item);
}
return null;
}
//gettes and setters
}
form.xhtml
<h:form id="frmPrincipal">
<h:panelGrid columns="2">
<h:outputText value="Guys: " />
<h:dataTable value="#{person.guys}" var="men" binding="#{person.dtGuys}" >
<h:column>
<p:inputText value="#{men}" valueChangeListener="#{person.addToList}" />
</h:column>
</h:dataTable>
<h:commandButton name="add" value="Add" action="#{person.addNewItem}" />
</h:panelGrid>
<br />
<h:commandButton id="submit" name="submit" value="Submit" action="#{person.save}"/>
</h:form>
Using jsf 2.0.10 and primefaces 3.5
Its because you don't have an scope for that bean, so its request scoped, so when you call the action the bean is created again, you can fix this using a sessionScope or conversationScope

multiple f:ajax calls in multiple h:selectOneMenu

Consider the following form:
1. User selects a value from the selectOneMenu "selectorDB"
2. Ajax call returns items for the second selectOneMenu and makes the whole "second" panelGroup rendered
3. User selects a value from the second selectOneMenu
4. Ajax call returns String which is placed inside of the inputText and panelGroup which contains that inputText rendered.
Everything works fine till im not selecting a value from the second selectOneMenu. Ajax of the fourth action is not even called. I've placed a couple of console System.outs to check if the listener is called and got nothing.
Is that possible to make something like the thing I'm attempting to do?
Thank you for any replies.
*.jsf:
<h:form>
<h:panelGroup id="first">
<h:outputLabel value="Select a database to make queries against" for="selectorDB" />
<h:selectOneMenu id="selectorDB" value="#{sparqlQuerier.chosenRing}">
<f:selectItem itemLabel="Select..." itemValue="0" />
<f:selectItems value="#{sparqlQuerier.ringTitles}" />
<f:ajax render="second third" listener="#{sparqlQuerier.firstListener}"/>
</h:selectOneMenu>
</h:panelGroup>
<br />
<h:panelGroup id="second">
<h:outputLabel rendered="#{sparqlQuerier.doRenderSecond}" value="Select a query to execute" for="selectorQuery" />
<h:selectOneMenu rendered="#{sparqlQuerier.doRenderSecond}" id="selectorQuery" value="#{sparqlQuerier.chosenQuery}">
<f:selectItem itemLabel="Select..." itemValue="0" />
<f:selectItems value="#{sparqlQuerier.queries}" />
<f:ajax render="third" listener="#{sparqlQuerier.secondListener}"/>
</h:selectOneMenu>
</h:panelGroup>
<br />
<h:panelGroup id="third">
<h:inputText rendered="#{sparqlQuerier.doRenderThird}" value="#{sparqlQuerier.queryBody}" onfocus="if (this.value == '#{sparqlQuerier.queryBody}') {this.value = '';}" onblur="if (this.value == '') {this.value ='#{sparqlQuerier.queryBody}';}" />
</h:panelGroup>
</h:form>
bean:
public void firstListener(AjaxBehaviorEvent event)
{
doRenderThird = false;
doRenderSecond = false;
if(chosenRing!=0)
{
doRenderSecond = true;
try
{
// returning rows from the database...
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
public void secondListener(AjaxBehaviorEvent event)
{
doRenderThird=false;
if(chosenQuery!=0)
{
if(chosenQuery==-1)
{
queryBody="body #1";
}
else
{
queryBody="body #2";
}
doRenderThird=true;
}
System.out.println(chosenQuery);
System.out.println(doRenderThird);
}

How to display and update a "sub-page" within a condition (using primefaces)

I have a scenario to achieve but I don't know how to do it(I'am using primefaces)
The scenario is:
I have a selectOneMenu that contain options that the user can choose one of them,
when the user choose an option ,a "form" or a "Sub-page" should appear below the selectOneMenu , the user should fill it.
The "Sub-page" change according to the choosen option
eg :option1 ---> Sub-Page1
option2 --->Sub-Page2 etc..
JSF
<h:selectOneMenu style="width:200px" immediate="true" value="#{ToolsKPI.myChoice}" onchange="submit()" valueChangeListener="#{BeanTest.selectChangeHandler}" required="true" >
<f:selectItems value="#{ToolsKPI.getMyListKPI()}" />
</h:selectOneMenu>
<p:panel rendered="#{BeanTest.showPanelBool}" >
<h1>KPI1</h1>
<br></br>
<h:inputText value="test1" />
</p:panel>
<p:panel rendered="#{BeanTest.showPanelBool1}" >
<br></br>
<h1>KPI2</h1>
<h:inputText value="test2" />
<h:inputText value="test3" />
</p:panel>
My Bean
public class BeanTest implements java.io.Serializable {
private String myChoice;
private boolean showPanelBool;
private boolean showPanelBool1;
public BeanTest() {
}
//getters ande setters
public void selectChangeHandler(ValueChangeEvent event){
myChoice = (String) event.getNewValue(); // Must however be the exact page URL. E.g. "contact.jsf".
FacesContext.getCurrentInstance().getExternalContext();
if(myChoice.equals("Number Of Closed issues") ){
this.showPanelBool = true;
} else{
this.showPanelBool = false;
this.showPanelBool1 = true;
}
FacesContext.getCurrentInstance().renderResponse();
}
}
You should really post some semblance of the code: a picture something. What you're probably looking for is a "p:outputPanel" component or something similar.
http://www.primefaces.org/showcase/ui/outputPanel.jsf
You can do something with a ValueChangeListener akin to
public void onSelectItem(ValueChangeEvent evt)
{
if("someValue".equals(evt.getNewValue())
showPageOne = true;//boolean
else
showPageTwo = true;//boolean
}
//JSF
<h:form id="myForm">
<h:selectOneMenu valueChangeListener="#{myBean.onSelectItem}" update="myForm">
<f:selectItems value="items">
</h:selectOneMenu>
<p:outputPanel rendered="#{myBean.showPageOne}">
hi I'm page one
</p:outputPanel>
<p:outputPanel rendered="#{myBean.showPageTwo}">
hi I'm page two
</p:outputPanel>
</h:form>
Sorry for the pseudo code, the examples on Primefaces will really help you here. OutputPanel has saved my bacon often. You'll need to specify an update target, but the example is really clear and easy to run. Play with it.
(Also Primefaces is fantastic you'll likely be very happy with their component suite)

Categories

Resources