Невозможно изолировать отображаемую область Ajax для пользовательского интерфейса: включить загруженный вид в richfaces 4.x - PullRequest
0 голосов
/ 30 декабря 2011

Я хочу разработать веб-приложение, содержащее «Область меню» и «Активная область». Эта «Активная область» указывает на страницу в управляемом компоненте «Контроллер» и загружает ее по запросу ajax. Загружаемая страница задается с помощью ajax-запроса через «A4j: Commandlink» и отображает «Активную область». Вот код.

1. Index.xhtml

<ui:composition template="template.xhtml">
      <ui:define name="menu">
           <ui:include src="menu.xhtml" />
      </ui:define>

      <ui:define name="body">
           <h:panel width="100%" id="mainPanel">
                     <ui:include id="MainIncludeArea" src="#{controller.currentView}"/>
           </h:panel>
      </ui:define>
 </ui:composition>

2. Menu.xhtml

<ui:composition>
      <h:form id="menuForm">
           <ul>
                <li><a4j:commandLink value="Include 1" render="mainPanel" actionListener="#{controller.setInclude1}" /> </li>
           </ul>
      </h:form>
 </ui:composition>

3. Include1.xhtml

<ui:composition>
      Included Page 1
      <h:form id="f1">
           <a4j:commandButton id="cb1" actionListener="#{controller.action}" value="click"/>
      </h:form>
 </ui:composition>

4. Controller.java

@ManagedBean
@ApplicationScoped
public class Controller {
    String currentView;
   public Controller() {
      this.currentView = "include.xhtml";
    }

   public void action() {
      System.out.println("### Button Clicked ###");
    }

     public void setInclude1() {
      currentView = "include_1.xhtml";
    }

    public String getCurrentView() {
      System.out.println(" ### returning view ###" + currentView);
      return currentView;
    }
}

Теперь, когда страница загружается в активную область, которая, как вы видите, содержит «a4j: commandButton» с actionListener, если кнопка нажата вместо вызова метода слушателя, страница загружается снова, и когда при повторном нажатии кнопки страница загружается и вызывается метод слушателя. Это означает, что вся страница обновляется снова, а затем устанавливается представление и вызывается метод. В richfaces 3.3.x я использовал «a4j: include» для активной области. Все работало нормально Теперь в richfaces 4.x я должен использовать компонент ui: include. 3.3.x имел компонент «a4j: region» для изоляции региона. Но в 4.x его поведение изменилось.

Теперь я не знаю, как изолировать этот регион для повторного рендеринга и запрос Ajax. Я хочу, чтобы изменялась только активная область, а не вся страница обновлялась.

Спасибо

1 Ответ

0 голосов
/ 02 января 2012

В настоящее время я использую составные компоненты в своем приложении JSF 2.0, и я часто сталкиваюсь с той же проблемой.Поэтому я использую этот вспомогательный класс :

public class ComponentResolver {
    /**
     * Returns the absolute path of a given {@link UIComponent}.
     * E.g. :namingContainer1:namingContainer2:componentId.
     *
     * @param currentComponent
     * @return The absolute path of the given component
     */
    public String getAbsoluteComponentPath(UIComponent currentComponent) {
        final char separatorChar = UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance());

        String path = "";
        if(!(currentComponent instanceof NamingContainer))
            path = currentComponent.getId();
        while(currentComponent != null) {
            if(currentComponent instanceof NamingContainer) {
                path = currentComponent.getId() + (!path.isEmpty() ? separatorChar : "") + path;
            }
            currentComponent = currentComponent.getParent();
        }
        path = separatorChar + path;
        return path;
    }

    /**
     * Returns a whitespace-separated list of the absolute paths of all given components.
     *
     * @param components The list of components
     * @return A whitespace-separated list of all absolute paths.
     * @see ComponentResolver#getAbsoluteComponentPath(UIComponent)
     */
    public String getAbsoluteComponentPaths(Collection<UIComponent> components) {
        String paths = "";
        for(UIComponent c : components) {
            if(!paths.isEmpty())
                paths += " ";
            paths += getAbsoluteComponentPath(c);
        }
        return paths;
    }

    /**
     * Finds all components with the given id, and returns a whitespace-separated list
     * of their absolute paths (e.g. <code>:j_id1:j_id2:myId :j_id1:j_id3:myId</code>).
     *
     * @param id The id to search the component tree for
     * @return Whitespace-separated list of absolute component paths
     * @see #resolveList(String)
     */
    public String resolve(String id) {
        List<UIComponent> components = resolveList(id);
        return getAbsoluteComponentPaths(components);
    }

    public String resolveWithoutRootPrefix(String id) {
        List<UIComponent> components = resolveList(id);
        String result = getAbsoluteComponentPaths(components);
        return result.substring(1, result.length());
    }

    /**
     * Finds all components with the given id by traversing the component tree.
     * @param id Id to search for.
     * @return List of components that have got this id.
     */
    public List<UIComponent> resolveList(String id)
    {
        return resolveList(id, FacesContext.getCurrentInstance().getViewRoot());
    }

    /**
     * Recursive function that traverses the component tree and accumulates all components
     * that match the given id.
     * @param id The id to look for
     * @param currentComponent Component of the tree to start traversal at
     * @return Accumulation of all components that match the given id
     */
    private List<UIComponent> resolveList(String id, UIComponent currentComponent) {
        List<UIComponent> accumulator = new LinkedList<UIComponent>();

        if(null != currentComponent.getId() && currentComponent.getId().equals(id)) {
            accumulator.add(currentComponent);
        }

        Iterator<UIComponent> childIt = currentComponent.getFacetsAndChildren();
        while(childIt.hasNext()) {
            UIComponent child = childIt.next();
            accumulator.addAll(resolveList(id, child));
        }

        return accumulator;
    }
}

Тогда вам просто нужно установить его как управляющий компонент и использовать его следующим образом:

#{componentResolver.resolve('myRegion')}

Тактеперь вам просто нужно установить идентификатор целевой области как myRegion и установить атрибут render вашей commandLink с предыдущим EL.

Это довольно сложно, но я не нашел другого решениядля работы с вложенными блоками в JSF 2.0.

(источник)

...