RichFaces h:selectOneMenu a4j:support not working when initialised with materialCSS multi_select() - material-design

Disclaimer - I am newbie to richfaces as I used to work on .net platform earlier :)
I am trying to change the theme of the RichFaces application with materialize css. I have a simple h:selectOneMenu as below
<h:selectOneMenu value="#{testBean.presetDate}" valueChangeListener="#{testBean.resetValues}" id="presetDate">
<f:selectItem itemValue="-1" itemDisabled="true" itemLabel="Select days" />
<f:selectItems value="#{testBean.listOfPresetDates}" />
<a4j:support event="onchange" ajaxSingle="true">
</a4j:support>
</h:selectOneMenu>
and my resetValues method inside testBean.java is as follows:
public void resetValues(ValueChangeEvent valueChangeEvent) {
//some processing here
}
and I have been initialising this selecOneMenu with materialize css multi_select() plugin as below:
$('select').material_select();
But whatever I do, the valueChangeListner doesn't trigger at all. I mean, it never calls the method in server. I also tried putting that method as actionListener in a4j:support and changing parameter of server method as ActionEvent, but even that doesn't help. Anything else I have to configure along with this?
Note: Earlier design had rich:combobox instead of selectOneMenu which was working fine with changeListener, but the plugin will not be able to convert this to required material select since, the above will not render select element, rather it renders table and inputs in DOM.
EDIT
Forgot to mention one thing. We are loading this page through ajax request as below:
<a4j:form id="pageForm" rendered="#{prevBean.selectedPage == 'bth'}">
<a4j:include viewId="/newPage.jsp" id="newPage" rendered="#{prevBean.selectedPage == 'bth'}" />
<script type="text/javascript">
jQuery(document).ready(function() {
initSelect_DatePicker();
});
</script>
</a4j:form>
This newPage.jsp contains above control. Will this be a cause for the above problem?

Related

CommandButton execution while rendering

Question: How can I prevent the execution of a while the website is rendering?
Thats where my Button sits:
<p:dialog widgetVar="newComment" height="200" width="500">
<h:form>
<h:panelGrid>
<h:outputText value="#{commentDialog.username}" />
<h:inputTextarea id="in_text" value="#{commentDialog.text}" />
<p:message for="in_text" />
</h:panelGrid>
<p:commandButton validateClient="true" value="Abschicken" ajax="true"
actionListener="#{popupRequestView.update}" action="PF('newComment').hide();update_popup();" />
</h:form>
</p:dialog>
The action attribute is intented to execute a backing bean action method on click, not to print some JavaScript code (which of course get executed immediately
You perhaps meant to use onclick or oncomplete instead. Like as in basic HTML, those on* attributes are intented to execute some JavaScript code during the specified HTML event ("click", "complete", etc).
oncomplete="PF('newComment').hide();update_popup();"
Another cause not visible in the information provided so far is that you forgot to register the p: XML namespace. Any <p:xxx> tags would then be printed as if it's plain text. Verify if a parent element somewhere in the markup has this:
xmlns:p="http://primefaces.org/ui"
Regardless, taking a JSF pause and learning some basic HTML/JavaScript wouldn't be a bad idea. After all, JSF is "just" a HTML/CSS/JS code generator.
you must use primefaces ajaxStatus to prevent click on button while rendering and execute ajax
ajaxStatus in primefaces showcase

onchange="submit()" reloads my PrimeFaces Mobile page

I am having a problem with my JSF project, where I am using PrimeFaces Mobile. This page has several pm:views
I have a list of radio buttons, which looks like this:
<p:selectOneRadio value="#{bean.currentElement}" converter="omnifaces.SelectItemsConverter"
onchange="submit()"
valueChangeListener="#{bean.elementChanged}">
<f:selectItems value="#{bean.currentItem.elements}" var="element"
itemLabel="#{element.elementName}" itemValue="#{element}" />
</p:selectOneRadio>
My valueChangeListener looks like this:
public void elementChanged(ValueChangeEvent e) {
currentElement = (Element) e.getNewValue();
System.out.println(getCurrentElement().getElementName());
}
The problem is, whenever I click on a radio button element, my page completely reloads to the start view, which has to do with the onchange="submit()". I have also tried f:ajax elements, but this doesn't seems to be working with my radio buttons, because I can't click them when I use this.
Is there a possiblty to just submit my current form or pm:view (without the f:ajax)?
PS: I have also tried exactly this on a single PrimeFaces Mobile page, which completely worked, since the application just consisted of one page.
When using PrimeFaces components, you should be using <p:ajax> instead of <f:ajax>. Just get rid of the onchange="submit()". This indeed invokes a synchronous (non-ajax) form submit which totally explains the page reload. You also need to replace valueChangeListener by <p:ajax listener>. The valueChangeListener is the wrong tool for the job whereby you're merely interested in invoking a JSF action method when the newly selected value is being set.
All in all, the rewrite should look like this:
<p:selectOneRadio value="#{bean.currentElement}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{bean.currentItem.elements}" var="element"
itemLabel="#{element.elementName}" itemValue="#{element}" />
<p:ajax listener="#{bean.elementChanged}" />
</p:selectOneRadio>
Don't forget to remove the ValueChangeEvent argument from the elementChanged() method. In order to access the selected value, just access the currentElement property directly.
See also:
When to use valueChangeListener or f:ajax listener?

Progress bar primefaces on backend processing

I would appreciate it if someone can give me some hints about progress bar and ajax back-end processing.
To clarify what I need following are details:
I have a command button to do some processing at the back-end.
I would like to show a progress bar that reach the 100% when the backing bean finishes processing back-end instructions.
I looked over many threads but no luck. Most of them did not show a concrete sample how to do that.
Below is a snippet of my code:
</h:panelGrid>
<p:commandButton id="btn" value="DoSomeAction"
styleClass="ui-priority-primary" update="panel"
onclick="PF('pbAjax').start();PF('startButton1').disable();"
widgetVar="startButton1"
actionListener="#{actionBean.DoSomeAction}" />
<p:progressBar widgetVar="pbAjax" ajax="true"
value="#{progressBean.progress}" labelTemplate="{value}%"
styleClass="animated">
<p:ajax event="complete" listener="#{progressBean.onComplete}"
update="growl" oncomplete="startButton2.enable()" />
</p:progressBar>
</p:panel>
This is the code for the Progress Brean:
#ManagedBean(name="progressBean")
public class ProgressBean implements Serializable {
private Integer progress;
public Integer getProgress() {
if(progress == null)
progress = 0;
else {
progress = progress + (int)(Math.random() * 35);
if(progress > 100)
progress = 100;
}
return progress;
}
public void setProgress(Integer progress) {
this.progress = progress;
}
public void onComplete() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Progress Completed", "Progress Completed"));
}
public void cancel() {
progress = null;
}
}
The result of this code is just an empty progress bar and nothing happen when I click on my button.
Thanks in advance.
It'll be easier if I simply walk you through my sample code since you have two beans and I don't know the interaction between them. You can use it to apply it to yours.
<p:commandButton>
<p:commandButton value="Start" type="button" onclick="pbAjax.start();startButton1.disable();" widgetVar="startButton1" />
Nothing impressive here. You have a commandButton with widgetVar="startButton1". When you click on it, onclick comes in and disables the commandButton. It also signals <p:progressBar> to start via pbAjax.start() (<p:progressBar> has widgetVar = "pbAjax.start()").
<p:progressBar>
<p:progressBar widgetVar="pbAjax" value="#{progressBean.progress}" ajax="true" labelTemplate="{value}%">
<p:ajax event="complete" listener="#{progressBean.onComplete}"
update="growl" oncomplete="startButton1.enable()"/>
</p:progressBar>
<p:progressBar> will simply keep calling #{progressBean.progress} to update the progress. When the progress reaches 100% <p:ajax> kicks in and calls #{progressBean.onComplete}. <p:commandButton> get re-enabled and <p:growl> gets updated. Notice how I'm not using PF(...). To be honest, I'm not sure if it makes a difference, I did not test.
Note
In your <p:progressBar> you have oncomplete="startButton2.enable(). It should be startButton1.enable() since your widgetVar value for your <p:commandButton> is startButton1.
Also, notice that I did not use styleClass="animated". With this, you'll just get the bland looking blue bar. If you want to use it then you need to take some extra steps. Looking at your code, it seems you're taking it straight from the PrimeFaces showcase so I'll also use their assets.
Using styleClass="animated"
First, you're going to create a folder called resources in your webapp folder (Web Pages for Netbeans). Then create a folder called css and add in a stylesheet called style.css. The directory structure will be like this: resources/css/style.css. In style.css you're going to have to define this rule. (Don't worry if this is confusing, I'll have the whole code below).
.animated .ui-progressbar-value {
background-image: url("#{resource['images/pbar-ani.gif']}");
}
Then you're going to create an images folder under resources and place the image
pbar-ani.gif in that folder (resources/images/pbar-ani.gif). Image below.
Make sure you have <h:outputStylesheet name='css/style.css' /> in <h:head> and add styleClass="animated" in <p:progressBar>.
Important!
If you are using PrimeFaces 3.5 like I am the image will just not display (including when you're not using styleClass). If you look closely at Firebug you will see the following error
Uncaught TypeError: Object #<Object> has no method 'easeInOutCirc'
One workaround I found for this is to simply use dummy <p:dialog>.
That's it.
You can get more information about the progressBar through the developer's guide.
In case you're wondering how I knew where to get the image you'll have to download the showcase. You can read this article to find out how to download the showcase.
In my opinion, when you really want to use the showcase code, it's better if you simply download the demo. Often time I'm either not seeing the complete picture or the code in the showcase has some mistakes
Anyway here's the sample code as promised. I'm using the same ProgressBean from the showcase (same as yours). Keep in mind that you will have to come up with the logic with how your object interacts with ProgressBean to update the progress bar.
Summary
<h:head>
<h:outputStylesheet name='css/style.css' />
</h:head>
<h:body>
<h:form >
<p:growl id="growl" />
<h3>Advanced Ajax ProgressBar</h3>
<p:commandButton value="Start" type="button" onclick="pbAjax.start();
startButton1.disable();" widgetVar="startButton1" />
<br /><br />
<p:progressBar widgetVar="pbAjax" value="#{progressBean.progress}" ajax="true" labelTemplate="{value}%" styleClass="animated">
<p:ajax event="complete" listener="#{progressBean.onComplete}"
update="growl" oncomplete="startButton1.enable()"/>
</p:progressBar>
<p:dialog></p:dialog><!-- For PrimeFaces 3.5 -->
</h:form>
</h:body>
and remember your directories
resources/css/style.css
resources/images/pbar-ani.gif

How populate a select tag in HTML to JSF 2?

I have this code which works fine in HTML as you can see, but how get the values of the <select /> tag to insert in my bean ?
Something like this:
<h:outputLabel for="state" value="State:" />
<h:selectOneMenu id="state" value="#{bean.state}" />
I'm trying a lot of things but nothing so far.
Any idea ?
This isn't going to work. JSF needs to know about all of the dropdown items.
Either use a plain HTML <select> element instead of <h:selectOneMenu> and grab the submitted value by #ManagedProperty or <f:viewParam>, or port that JS code to JSF backing bean code so that you can use <f:selectItems>. You can use <f:ajax> to fill and render the 2nd dropdown.
The Javascript functions seem to take the ids of the selects.
If you do <h:form prependId="false"> and <h:selectOneMenu id="city" then "city" will be the id of the select rendered by JSF. Just pass that ids to the functions.
<h:form prependId="false">
<h:selectOneMenu id="city" value="#{bean.selectedCity}">
</h:selectOneMenu>
<h:selectOneMenu id="state" value="#{bean.selectedState}">
</h:selectOneMenu>
</h:form>
<script language="JavaScript" type="text/javascript" charset="utf-8">
$(document).ready(function() {
new dgCidadesEstados({
cidade: document.getElementById('city'),
estado: document.getElementById('state')
});
});
</script>
You need to use <h:selectItems> tag. A nice introduction is here and here .
I have an stupid (or funny) idea when i integrate CKEditor into JSF (take a look, it is wonderful).
Thus, CKEditor does not support JSF fully, but it supports HTML and JS (jQuery) themselves. When editing in CKEditor, it create other tags for user to input on it, and when user submit information to server, nothing found in that. So I created a <h:inputTextArea value="#{bean.textEditor}"/> and when user submit, it run a script to set its value to that <h:inputTextArea/> :)
Back to your question, i would fire a JS script to do that trick :).You can use <h:inputHidden value=#{bean.city}/> and onclick event on submit button or something like that to do that trick :). But in this case, you have to validate data yourself to make sure that this information is vaild.

Can't define a event and bind an <a4j:support/> on this event at the same time

Let's consider this simple code:
<h:form id="myForm">
<h:inputText id="myInput">
<a4j:support event="onchange" actionListener="#{myBean.doSomething}"/>
</h:inputText>
</h:form>
this will generate the following HTML code:
<input id="myForm:myInput" type="text" name="myForm:myInput" onchange="A4J.AJAX.Submit(...)" />
Now, I just add something in the onchange event of my <h:inputText>:
<h:form id="myForm">
<h:inputText id="myInput" onchange="alert('foobar');">
<a4j:support event="onchange" actionListener="#{myBean.doSomething}"/>
</h:inputText>
</h:form>
This will generate the following HTML code:
<input id="myForm:myInput" type="text" name="myForm:myInput" onchange="alert('foobar');" />
As you can see, the Ajax code is not added anymore. This is a really strange behavior as far as I am concerned. Why the <a4j:support> does not attach the Ajax call if the event is already defined in the input field?
So my question is how to make the <a4j:support> working on an event that is already defined in the input? Of course, the solution must run both the Javascript code defined in onchange and the Ajax call.
In others words, I would like to have the following HTML:
<input id="myForm:myInput" type="text" name="myForm:myInput" onchange="alert('foobar'); A4J.AJAX.Submit(...)" />
I am using Richfaces 3.3.2 and JSF 1.2
EDIT
Of course, I can move the onchange Javascript code in the onsubmit attribute of the <a4j:support>, doing something like that:
<h:inputText id="myInput">
<a4j:support onsubmit="alert('foobar');" event="onchange" actionListener="#{myBean.doSomething}"/>
</h:inputText>
But is it the only way??
If this behaviour is not explicitly documented, I would consider this as a bug in Ajax4jsf. Report it to Ajax4jsf/RichFaces guys over there at JBoss.org. I've seen problems like that before with <a4j:commandButton onclick="someFunction()">
I already had this problem before, and I found that RichFaces 3.3.x will execute only the code for the onchange event defined with a4j:support and will ignore the onchange code defined with the JSF component.
In my case the workaround was simple, for my case it was valid to use other event instead of "onchange" (not sure if it was onclick or onselect), so I attached my code to this other event and my code worked, but I'm not sure if this could work for you. If you really need the onchange event for both elements, you'll have to do just as BalusC said and report it to the RichFaces folks.
More about the context
In fact, I can't really modify the event value of the <a4j:support>, like suggesteed by Abel Morelos, because what I am trying to do is to add a custom component that execute some client-side validation. This validation calls a Javascript function, so my custom component modifies the onchange value of his parent.
My JSF code will looks like:
<h:inputText id="myInput">
<my:validation .../>
<a4j:support event="onchange" actionListener="#{myBean.doSomething}"/>
</h:inputText>
This code is quite equivalent to the following code, except that the onchange of the <h:inputText> is added automatically by my component:
<h:inputText id="myInput" onchange="if (!checkSomeValidation()) { return false; }">
<a4j:support event="onchange" actionListener="#{myBean.doSomething}"/>
</h:inputText>
So as you can understand, my custom component directly modifies the onchange event of the <h:inputText>, and due to the problem with <a4j:support>, the Ajax call is not binded to the input component at the end.
The solution
When linked to a JSF component, the <a4j:support> will "transform" itself to a facet, whose name is org.ajax4jsf.ajax.SUPPORTxxx, where xxx is the event name. So in my case, the <h:inputText> will have a facet named org.ajax4jsf.ajax.SUPPORTonchange.
So what I do in my Java code of my custom component, is to check if the parent (the <h:inputText> here), has such a facet.
If no, it means that the parent has no <a4j:support event="onchange"/> linked to it. So in this case, I modify the onchange attribute of my <h:inputText/>
If yes, it means that there is a <a4j:support event="onchange"/> linked to the parent. So I modify the facet itself using the following code:
HtmlAjaxSupport facet = (HtmlAjaxSupport) getParent().getFacet("org.ajax4jsf.ajax.SUPPORTonchange");
if (facet != null) {
facet.setOnsubmit("my Javascript code goes here");
} else {
getParent().setOnchange("my Javascript goes here");
}

Resources