JavaScript: список не обновляется после всплывающего поиска

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

}
Теги:
jsf
seam

2 ответа

1
Лучший ответ

Я не понимаю, почему вы хотите заполнить свой списокBox, используя всплывающее окно.

Но если вы измените базовые значения 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>

Вы также можете использовать <rich:modalPanel> вместо всплывающего окна, чтобы оставаться на одной странице и более легко взаимодействовать с вашими компонентами jsf.

  • 0
    Ах да, все просто и работает!
  • 0
    Рад, что читать это помогло :)
1

На странице во всплывающем окне запускается некоторый код на стороне сервера, который создает новые параметры для раскрывающегося меню. Это не влияет на родительскую страницу, пока родительская страница не будет перезагружена и не будет восстановлена сервером. Чтобы не перезагружать страницу, вам необходимо создать и выбрать новую опцию, используя код 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/

Ещё вопросы

Сообщество Overcoder
Наверх
Меню