Получение поддержки bean значения с помощью Javascript

JSF 2.0, Mojarra 2.0.1, PrimeFaces 3.4.1

Есть похожие вопросы, но мне нужно sth. еще; Функция javascript должна ждать метода поддержки bean, который заполняет переменную, которую нужно вытащить из js-функции. Я хочу сказать:

<p:commandLink action="#{statusBean.getStatuses}" oncomplete="afterLoad()"/>

Предполагая, что функция js просто получает значение и печатает его на экране.

function afterLoad() {    
    alert("#{statusBean.size}");
}

И вот день рождения:

@ManagedBean
@ViewScoped
public class StatusBean {
    public int size=0;
    List<Status> panelList = new ArrayList<Status>();
    public void getStatuses() {
        this.panelList = fillList();
        this.size = panelList.size(); //Assuming 3
    }
    //getter and setters
}

Таким образом, функция сообщает размер как 0, который является его начальным значением, а мы ожидаем увидеть 3.

Как это работает: Если я добавлю аннотацию @PostConstruct к bean, голова наверняка получит правильный размер, потому что bean уже сконструирован до загрузки страницы. Но это означает избыточные процессы, стоимость которых требуется только после действия команды. Итак, как отложить функцию js? Любые идеи?

Ответ 1

JSF/EL и HTML/JS не работают синхронно. Вместо этого JSF/EL запускается на веб-сервере и создает HTML/JS, который, в свою очередь, работает в webbrowser. Откройте страницу в браузере, щелкните правой кнопкой мыши и выберите Источник. Видите ли, нет ни одной строки JSF/EL. Это один и все HTML/JS. Вместо вашей функции JS вы увидите:

function afterLoad() {    
    alert("0");
}

Именно эта функция JS вызывается при выполнении действия вашей кнопки. Таким образом, результат вполне ожидаемый.

В принципе, вы хотите, чтобы JSF повторно отображал эту часть JS.

<p:commandLink action="#{statusBean.getStatuses}" update="afterLoad" oncomplete="afterLoad()"/>
<h:panelGroup id="afterLoad">
    <h:outputScript>
        function afterLoad() {    
            alert("#{statusBean.size}");
        }
    </h:outputScript>
</h:panelGroup>

В зависимости от конкретного функционального требования, о котором вы ничего не говорили, могут быть более элегантные способы. Например, RequestContext#execute(), <o:onloadScript> и т.д.

Ответ 2

EL в вашем JavaScript вычисляется при рендеринге страницы, и вы можете обновить его контейнер (если он находится в некотором компоненте JSF), но я бы предложил другой подход.

Как вы делаете запрос AJAX, вы можете добавить параметр обратного вызова в метод getStatuses(). Вы можете использовать утилиту Primefaces RequestContext addCallBackParam() для этого:

public void getStatuses() {
    this.panelList = fillList();
    this.size = panelList.size();
    RequestContext.getCurrentInstance().addCallBackParam("size", this.size);
}

и вы можете использовать этот параметр в xhtml:

<p:commandLink action="#{statusBean.getStatuses}" oncomplete="afterLoad(xhr, status, args)"/>

<script type="text/javascript">
  function afterLoad(xhr, status, args) {    
    alert(args.size);
  }
</script>