我目前有一个列表框(搜索条件的一部分),它表示通过弹出窗口一次检索一个字符串的列表。但是,当弹出窗口关闭时,所选的String永远不会添加到列表框中。 (我已确认隐藏变量已更新,如果您在执行搜索后导航离开页面并导航回来,则列表框会正确显示我之前从弹出窗口中选择的字符串)。任何帮助将不胜感激!
<script type="text/javascript">
function selectBook(bookId, extendedBookName) {
var idInput = jQuery("#myForm\\:bookNames");
if (idInput.val() == "") {
idInput.val(extendedBookName);
} else {
idInput.val(idInput.val() + '@@@' + extendedBookName);
}
}
</script>
...
<h:form id="myForm">
...
<ui:define name="form-fields">
<h:selectOneListbox id="booksListBox" size="3" style="width:470px">
<s:selectItems var="_var" value="#{bean.searchCriteria.bookNames}" label="#{_var}" noSelectionLabel="" />
</h:selectOneListbox>
<h:outputLink onclick="return openNewWindow('#{bean.booksLookupUrl}?#{bean.bookLookupParameters}', 'book');"
target="_blank">
<h:inputHidden id="bookNames" value="#{bean.searchCriteria.bookNames}" converter="StringListConverter"/>
<h:outputText value="Add"/>
</h:outputLink>
</ui:define>
...
</h:form>
这是属于查找窗口的javaScript。这会调用selectBook函数
function selectBook(bookId, extendedBookName) {
var extendedName = unescape(extendedBookName);
window.opener.selectBook(bookId, extendedName);
window.close();
}
对于我的Java代码......
public class BookSearchCriteria implements Serializable {
...
private List<String> bookNames = new ArrayList<String>();
public List<String> getBookNames() {
return bookNames;
}
public void setBookNames(List<String> bookNames) {
this.bookNames = bookNames;
}
StringListConverter代码......
@FacesConverter("myStringListConverter")
public class StringListConverter implements Converter {
// this is used as a regex, so choose other separator carefully
private static final String MY_SEPARATOR = "@@@";
@Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
if (value == null) {
return new ArrayList<String>();
}
return new ArrayList<String>(Arrays.asList(value.split(MY_SEPARATOR)));
}
@Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
if (value == null) {
return "";
}
return join((List<String>) value, MY_SEPARATOR);
}
/**
* Joins a String list, src: http://stackoverflow.com/q/1751844/149872
*
* @param list
* @param conjunction
* @return
*/
public static String join(List<String> list, String conjunction) {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (String item : list) {
if (first) {
first = false;
} else {
sb.append(conjunction);
}
sb.append(item);
}
return sb.toString();
}
}
答案 0 :(得分:1)
弹出窗口中的页面正在运行一些服务器端 Java代码,该代码为下拉菜单创建新选项。在父页面由服务器重新加载和重新生成之前,这对父页面没有任何影响。为避免重新加载页面,您需要使用客户端 JavaScript / jQuery代码创建并选择新选项。
假设结果选项的HTML代码看起来像<option value="bookId">extendedBookName</option>
,您可以使用:
<script>
function addBook(bookId, extendedBookName) {
var newOption = jQuery('<option>').val(bookId).text(extendedBookName);
var idInput = jQuery('#myForm\\:bookNames');
idInput.append(newOption).val(bookId);
}
</script>
或者,如果不保证弹出窗口中的选择是新的,那么您需要动态确定是否需要创建选项以避免重复:
<script>
function addBook(bookId, extendedBookName) {
var idInput = jQuery('#myForm\\:bookNames');
if (idInput.val(bookId).val() != bookId) {
var newOption = jQuery('<option>').val(bookId).text(extendedBookName);
idInput.append(newOption).val(bookId);
}
}
</script>
答案 1 :(得分:1)
我真的不明白为什么要使用弹出窗口填充listBox。
但是如果修改底层bean值,则需要重新呈现<h:selectOneListbox/>
以反映这些更改。如果您正在使用(或可以使用)richfaces framework,可以通过ajax调用轻松完成。
名为<a4j:jsFunction/>
的{{3}}组件可以完成这项工作。例如,在您的父页面中添加:
<a4j:jsFunction name="refreshListbox" reRender="booksListBox" limitToList="true"/>
并在弹出窗口中选择新书籍时调用此js函数:
<script type="text/javascript">
window.opener.refreshListbox();
</script>
您还可以使用<rich:modalPanel>
代替弹出窗口来保持同一页面,并更轻松地与您的jsf组件进行交互。