LINUX.ORG.RU

JSF, ActionListener и JS API

 , ,


0

1

Я делаю составной компонент на JSF. В нём я подключаю вот эту js-либу и div. Либа строит диаграмму с элементами (на основе xml или json). В ней предусмотрено API, в том числе, обработка событий: выбор задачи, её передвижение и тд. Есть ли возможность связать некоторые события из js-либы со слушателями jsf?

Т.е. я хочу, чтобы пользователь либы мог вставить компонент на страничку и смог указать свои обработчики событий:

<foo:mycomponent tasks="#{taskBean.tasksXML}"
chooseTaskListener="#{someBean.chooseTaskCustomListener}"
changeTaskListener="#{someBean.changeTaskCustomListener}"/>

Ну а в слушателях пользователь может, например, записать задачу в БД или файл, или выполнить какое-нибудь другое действие. Возможно ли это?

У меня есть идея, но не знаю, как правильно её реализовать.

gantt.attachEvent("onTaskSelected", function(id,item){
    // тут хотелось бы сделать ajax-запрос(?), 
    // который вызвал бы #{someBean.chooseTaskCustomListener}, т.е. то, что передал пользователь в мой компонент
    // но как? использовать jsf-тег в js-коде?
    // или сделать что-то типа 'emit' какого-нибудь события из jsf.js?
});



Последнее исправление: memnek (всего исправлений: 4)

Если не хотите ковыряться с полноценным компонентом, то можете использовать какой-нибудь a4j:function, который дёрнете из js кода. Правильный вариант - писать компонент, но это несколько муторно.

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

ну мне нужен именно компонент. чтобы потом его можно было в jar упаковать и распространять.

я нашел что-то на SO. там говорят, что можно подписаться на событие из промежуточного компонента. но примеров я пока не очень нашел.

memnek
() автор топика
Ответ на: комментарий от memnek

Вы в любом случае получите компонент, просто в пером у вас он будет композитный.

я нашел что-то на SO

SO? Неважно, гугл вам в помощь, у ИБМа полно статей по жсфу, например http://www.ibm.com/developerworks/web/library/j-jsf2fu-0410/index.html

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

SO?

StackOverflow

Ну у ИБМ немного не то. Там есть компоненты, и к ним вешается слушатель. У меня по-другому: есть событие, генерируемое JS и некий DOM, который тоже генерируется JS-ом. т.о. я не могу написать actionListener=«#{someListener}». мне надо каким-то образом связать js-событие и обработать его. а как, я пока не очень понимаю.

memnek
() автор топика
Ответ на: комментарий от ya-betmen

я просто не особо понял, как его использовать. я могу вызвать этот метод в gantt.attachEvent(«onTaskSelected», function(...){...}). но как соединиться со слушателем? можно примерчик?

memnek
() автор топика
Ответ на: комментарий от ya-betmen

кстати, когда вставляю компонент, он тащит в дом второй html тэг. как вылечить это?

memnek
() автор топика
Последнее исправление: memnek (всего исправлений: 1)

Решение, кому интересно

Как оказалось, не всё так просто. Из js нельзя вызвать какой-либо метод бина даже через всякие jsf.ajax.request. Приходится извращаться:

    <h:outputScript>
        gantt.attachEvent("onTaskSelected", function(id, item) {
            document.getElementById('#{someData.clientId}').value = id;
            document.getElementById('#{invisibleClickTarget.clientId}').click();
        });
    </h:outputScript>
    <h:form id="hiddenForm" style="display: none;">
        <h:inputHidden id="someData" binding="#{someData}" value="#{customEventBean.task}" />
        <h:commandButton id="invisibleClickTarget" binding="#{invisibleClickTarget}">
            <f:ajax execute="@form" listener="#{customEventBean.listener()}"/>
        </h:commandButton>
    </h:form>

Ну а в соответствующем бине собственно реализация слушателя.

memnek
() автор топика
Последнее исправление: memnek (всего исправлений: 1)
Ответ на: Решение, кому интересно от memnek

Из js нельзя вызвать какой-либо метод бина даже через всякие jsf.ajax.request

Можно, jsf.ajax.request естественно просто отсылает событие, обработкой и вызовом метода должен заниматься компонент.

Приходится извращаться:

Если не разбираться то приходиться.

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

У меня время поджимало. Я нашел решение, которое работает.

Я был бы очень признателен, если бы Вы написали, что нужно вставить в этот код

gantt.attachEvent("onAfterTaskAdd", function(id, item) {
    var task = prepareTask(item); // подготавливаем данные
    // код вставить сюда
});
, чтобы вызвать функцию добавления задачи, которую пользователь передает при создании компонента.

memnek
() автор топика
Последнее исправление: memnek (всего исправлений: 1)
Ответ на: комментарий от memnek
jsf.ajax.request(элемент,событие,{'javax.faces.event':"тип эвента", 'execute':"что пойдёт в пост", 'render': "что обновить"})

За точность в написании параметров не ручаюсь, пишу по памяти.

Но на стороне компонента вы должны создать AjaxBehavior, который бы обработал ваше событие, указываете ему метод в бине, который будет слушателем и когда жсф поймает событие он дёрнет ваш обработчик. Главное, что б ид компонента сопал - иначе не найдёт.

По идее писать напрямую jsf.ajax.request это костыль, гуманнее будет взять тег f:ajax (именно он и создаёт AjaxBehavior). Поэтому в компоненте вам не нужно будет создавать его самому, при рендеринге компонента просто берёте из бихейвера нагенеренный скрипт и втыкаете в любой удобный вам кусок компонента.

Пишу по памяти т.к. ковырять апи жсфа не ни времени не желания, погуглите jsf ajax behaviors, статьи есть. В коде самих жсф компонентов - куча примеров как это делается.

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

только проблема в том, что у меня нет элемента. он создаётся JS-ом. вся моя html-страница выглядит так:

<html ...>
<f:view>
  <h:body>
    <h:outputScript library="js" value="jslib.js" target="head"/>
    <div id="foo"></div>
    <h:outputScript>
      jslib.init("foo");
    </h:outputScript>
  </h:body>
<f:/view>
</html>

memnek
() автор топика
Ответ на: комментарий от memnek

только проблема в том, что у меня нет элемента.

Так сделайте компонент.

Вот это вот

<div id=«foo»></div>
jslib.init(«foo»);

Должен делать компонент, а ещё он должен передавать в init листенеры.

PS. Мне кажется зря вы взяли жсф.

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

У меня всё и так делается в компоненте: добавляется и инициализируется жс либа, выводится див. вот компонент. вот примерный код компонента:

<html ...>
<composite:interface>
    <composite:attribute name="tasksJSONData" required="true"/>
    <!-- теперь поля для событий -->
    <composite:attribute name="taskAddListener" 
    method-signature="java.lang.String action()"/>
    <composite:attribute name="taskAddData"/>
    <!-- тоже самое для остальных событий -->
</composite:interface>
<composite:implementation>
    <h:outputScript library="js" value="lib.js" target="head"/>
    <div id="foo"></div>
    <h:outputScript>
        lib.init("foo");
    </h:outputScript>
    <!-- далее идут связи событий -->
    <h:outputScript>
        lib.attachEvent("onAfterTaskAdd", function(id, item) {
            что тут вызывать? какой элемент передавать в jsf.ajax.request, 
            если на странице (до рендеринга) есть только 1 див и больше никаких jsf-компонентов? 
            можно только получить js-объект с данными (по id или использовать 2-й параметр item).
        });
    </h:outputScript>
</composite:implementation>
</html>

Теперь как использовать. Пользователь реализует нужные функции-слушатели и передает их при создании бина:

<html ...>
<h:body>
<myComponentNS:myComponent tasksJSONData="#{someBean.tasksJSONData}" 
taskAddListener="#{someBean.taskAddListener}"
taskAddData="#{someBean.taskAddData}"/>
</h:body>
</html>

При этом, пользователь сам должен создать в своем проекте бин, реализовать там методы getTasksJSONData, taskAddListener, setTaskAddData.

PS Надо было взять. Сам бы я использовал что-то другое

memnek
() автор топика
Ответ на: комментарий от memnek

У вас должен быть класс, лежащий под компонентом, он должен иметь аннотацию @FacesComponent и UIComponentBase в качестве папы. Там будут методы типа encode/decode и т.д. в этих методах вы и должны набить содержимое компонента, с генерацией скриптов и т.п. Ещё раз повторю, в интернете полно статей и примеров как это сделать.

ya-betmen ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.