2015-10-26 2 views
1

Я пытаюсь выгрузить всплывающие окна в моем проекте JSF 2 с использованием составных компонентов.Доступ к составным составным элементам JSF в JavaScript

В этой базе кода используются Icefaces 3.3.0 (с их уровнем совместимости 1.8.2 по историческим причинам), Mojarra 2.2.7 и Glassfish 4.1.

У меня есть input.xhtml, который обеспечивает ввод текста и использует всплывающее окно с двумя кнопками (ok/cancel), которое, в свою очередь, основывается на основном всплывающем окне.

input.xhtml:

<composite:interface> 
    <!-- ... --> 
    <composite:editableValueHolder name="forInput" targets="theInput"/> 
</composite:interface> 
<composite:implementation> 
    <my:popup2Buttons> 
     <ice:inputText id="theInput" value="..."/> 
     <script>setInputFocus("#{cc.clientId}:theInput");</script> 
    </my:popup2Buttons> 
</composite:implementation>   

popup2buttons.xhtml:

<composite:interface> 
    <!-- ... --> 
</composite:interface> 
<composite:implementation> 
    <my:popup> 
     <composite:insertChildren/> 
     <ice:commandButton id="OkButton" 
      value="Ok" 
      actionListener="..."/> 
     <ice:commandButton id="CancelButton" 
       value="Cancel" 
       actionListener="..."/> 
    </my:popup>      
</composite:implementation> 

popup.xhtml:

<composite:interface> 
    <!-- ... --> 
</composite:interface> 
<composite:implementation> 
    <script> 
    function setInputFocus(id) { 
     document.getElementById(id).focus(); 
    } 
    </script> 

    <ice:panelPopup> 
     <f:facet name="body"> 
      <h:panelGroup> 
       <composite:insertChildren/> 
      </h:panelGroup> 
     </f:facet> 
    </ice:panelPopup> 
</composite:implementation> 

Всплывающее работает в основном, как и ожидалось, то есть, я могу ввести что-то , кнопки ok и cancel работают, а также работает валидация.

Не работает мой код JavaScript, который пытается сфокусировать ввод при всплывании.

Когда я смотрю страницу в Firebug, я вижу, что идентификатор ввода - это MyForm:j_idt63:j_idt64:j_idt67:theInput, но код JavaScript пытается сфокусировать элемент с ID MyForm:j_idt63:theInput.

Почему #{cc.clientId} в input.xhtml Неправильный идентификатор, который вводит в конце концов? Что мне нужно сделать, чтобы сделать эту работу?

Я видел BalusC's hint on adding a binding, но мне не нужна привязка, чтобы составной компонент не зависел от каких-либо бэкэндов.

Есть ли что-то еще, что мне не хватает здесь?

ответ

2

Составные компоненты неявно naming containers. То есть они добавляют свой идентификатор к идентификатору клиента. Это позволяет использовать несколько из них в одном представлении без их дочерних элементов, вызывающих дубликаты идентификаторов в сгенерированном HTML-выходе.

В вашем конкретном случае вы завернули поле ввода в другом композите, который, в свою очередь, завернут еще один составной. Если вы абсолютно уверены, что вам не нужно несколько контейнеров для именования, обертывающих друг друга в этой конкретной композиции, то те (popup2buttons.xhtml и popup.xhtml), вероятно, не должны быть композитами, а скорее <ui:decorate> шаблонами или <ui:composition> tagfiles. См. Также When to use <ui:include>, tag files, composite components and/or custom components?

Возвращаясь к технической проблеме, это вызвано тем, что #{cc.clientId} не ссылается на идентификатор вложенного составного компонента, а на текущий составной компонент. И, таким образом, это не будет. Что касается потенциального решения с binding, ответ, который вы нашли, нигде не говорит о том, что для этого вам нужно использовать бэк-компонент. Код binding="#{foo}" в ответе был как есть. Это действительно так, без свойства bean, см. Также JSF component binding without bean property. Тем не менее, эта конструкция действительно завершится неудачно, если вы включите один и тот же составной несколько раз в один и тот же вид, и, таким образом, несколько компонентов имеют один и тот же binding="#{foo}".Он действительно не должен использоваться несколькими компонентами, см. Также What is component binding in JSF? When it is preferred to be used?

Чтобы решить эту проблему без бэк-компонента, вы можете использовать так называемый компонент поддержки.

com.example.InputComposite

@FacesComponent("inputComposite") 
public class InputComposite extends UINamingContainer { 

    private UIInput input; 

    // +getter+setter. 
} 

input.xhtml

<cc:interface componentType="inputComposite"> 
    ... 
</cc:interface> 
<cc:implementation> 
    ... 
    <h:inputText binding="#{cc.input}" ... /> 
    <script>setInputFocus("#{cc.input.clientId}");</script> 
    ... 
</cc:implementation> 

Альтернативой переработать их в шаблонах или тег-файлов. Будьте осторожны, чтобы вы не переоценивали/не использовали композиты.

+0

Метод привязки, похоже, работает только для входов, но не для, например, 'CommandButton'. Это правильно или я чего-то не хватает? Когда я добавляю атрибут 'binding =" # {okButton} "' к кнопке, он не будет отображаться. Это не было частью первоначального вопроса; Я пытаюсь иметь обработчик события onKeyPress на входе и нажимать кнопку ok, когда пользователь нажимает кнопку ввода и кнопку отмены, когда пользователь нажимает esc. – Robert

+0

Это может произойти, если несколько компонентов кнопок имеют один и тот же «привязку». Вы должны использовать 'binding =" # {cc.okButton} "' как объяснено в ответе. – BalusC

Смежные вопросы