JavaScript:弹出查找后没有更新列表框

时间:2013-09-26 00:12:13

标签: javascript jquery jsf seam

我目前有一个列表框(搜索条件的一部分),它表示通过弹出窗口一次检索一个字符串的列表。但是,当弹出窗口关闭时,所选的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();
    }

}

2 个答案:

答案 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>

演示:http://jsfiddle.net/5Cwjk/

或者,如果不保证弹出窗口中的选择是新的,那么您需要动态确定是否需要创建选项以避免重复:

<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>

演示:http://jsfiddle.net/nTtY9/1/

答案 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组件进行交互。