В настоящее время у меня есть список (часть критериев поиска), который представляет список строк, которые извлекаются по одному во всплывающем окне. Однако, когда всплывающее окно закрывается, выбранная строка никогда не добавляется в список. (Я подтвердил, что скрытая переменная обновлена, и если вы перемещаетесь в сторону от страницы после того, как поиск выполняется и перемещается назад, в окне списка правильно отображаются строки, которые я выбрал из всплывающего ранее). Любая помощь будет принята с благодарностью!
<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();
}
}
Я не понимаю, почему вы хотите заполнить свой список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.
На странице во всплывающем окне запускается некоторый код на стороне сервера, который создает новые параметры для раскрывающегося меню. Это не влияет на родительскую страницу, пока родительская страница не будет перезагружена и не будет восстановлена сервером. Чтобы не перезагружать страницу, вам необходимо создать и выбрать новую опцию, используя код 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>