问题
I'm working with Mojarra JSF 2.1.28 and Primefaces 3.5. I want to implement a client-side transferring input for the p:pickList component, where the user types something and the value is searched through the labels at the list of available elements, then it's transferred to the target list. That's how my code looks like:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<script>
//Just for testing, transfer the second element
//to the target list when document is ready. Works well
$(document).ready(function(string) {
transfer("name2");
});
//Transfer function. It takes each list item from the source list and checks if it matches with the given pattern
//If it does, moves it to the target list
function transfer(string) {
$(".ui-picklist-source li").each(function() {
var re = new RegExp(string);
if ($(this).attr('data-item-label').match(re)) {
$(".ui-picklist-target").append($(this));
}
});
};
</script>
<h:form>
<p:inputText
onkeypress="if (event.keyCode == 13) { transfer(this.value); return false;}" />
</h:form>
<h:form id="form">
<p:pickList value="#{bean.elements}" var="element"
itemLabel="#{element.name}" itemValue="#{element.name}" id="picklist" />
<p:commandButton value="Send" action="#{bean.send}" />
</h:form>
</h:body>
</html>
@ManagedBean
@ViewScoped
public class Bean implements Serializable{
public class Element {
private String name;
public Element(String n) {
name = n;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Element [name=" + name + "]";
}
}
private DualListModel<Element> elements;
public Bean() {
List<Element> source = new ArrayList<Bean.Element>();
List<Element> target = new ArrayList<Bean.Element>();
source.add(new Element("name1"));
source.add(new Element("name2"));
elements = new DualListModel<Bean.Element>(source, target);
}
public DualListModel<Element> getElements() {
return elements;
}
public void send() {
System.out.println("Available: " + elements.getSource() + " assigned: "
+ elements.getTarget());
}
public void setElements(DualListModel<Element> elements) {
this.elements = elements;
}
}
Well, in this test case, there are two items to play with, name1 and name2. When page loads, I use $(document).ready() to call my transfer(string) function in order to move name2 to the target list. Page gets properly loaded and if we click on Send button, we get the second element properly assigned.
Problem comes when calling the function using the p:inputText component. Here, we listen to the Enter key event to send the current given value and perform a transfer. At client side it works fair enough, it behaves as expected. However, when clicking on Send, model doesn't get properly updated at server side.
I infer this is caused by the view state kept by JSF, but how to deal with this? Is there a way to implement it or do I have to stick to Ajax requests?
回答1:
The "right" way to achieve this is to use Primefaces's Javascript API of
PrimeFaces.widget.PickList
Assuming your widgetVar is pickListWV, here's how you would do:
function transfer(string) {
PF('pickListWV').sourceList.children().each(function() {
var re = new RegExp(string, "i");
if ($(this).attr('data-item-label').match(re)) {
PF('pickListWV').selectItem($(this));// select the item
PF('pickListWV').add();// add it to the target
}
});
}
EDIT: Also you can make it more interesting, like live filtering..
<p:inputText
onkeypress="if (event.keyCode == 13) { transfer(this.value); return false;} else{PF('pickListWV').filter(this.value, PF('pickListWV').sourceList)}" />
EDIT 2:
As I can see that you have a case-sensitive match, so you have to declare your RegExp as case-insensitive
var re = new RegExp(string, "i");
Here's a small working example on github, and a working demo as requested :)
Hope this helps.
来源:https://stackoverflow.com/questions/22559619/building-a-client-side-transfer-method-for-ppicklist