0

我目前有一个列表框(搜索条件的一部分),它表示通过弹出窗口一次检索一个字符串的列表。但是,当弹出窗口关闭时,所选字符串永远不会添加到列表框中。(我已经确认隐藏变量已更新,如果您在执行搜索后离开页面并导航回来,列表框会正确显示我之前从弹出窗口中选择的字符串)。任何帮助将不胜感激!

    <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();
    }

}
4

2 回答 2

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/

于 2013-10-01T01:38:35.890 回答
1

我真的不明白您为什么要使用弹出窗口填充您的列表框。

但是如果你修改了底层的 bean 值,你需要重新渲染<h:selectOneListbox/>来反映这些变化。如果您正在使用(或可以使用)richfaces 框架,则可以通过 ajax 调用轻松完成。

调用的ajax4jsf组件<a4j:jsFunction/>可以完成这项工作。例如在您的父页面中添加:

<a4j:jsFunction name="refreshListbox" reRender="booksListBox" limitToList="true"/>

并且在您的弹出窗口中,只需在选择新账面价值时调用此 js 函数:

<script type="text/javascript">
    window.opener.refreshListbox();
</script>

您还可以使用 a<rich:modalPanel>而不是弹出窗口来保持在同一页面中并更轻松地与您的 jsf 组件交互。

于 2013-10-01T15:27:34.487 回答