wake-up-neo.com

Komponente nach ID in JSF suchen

Ich möchte einige UIComponent von Managed Bean anhand der von mir angegebenen ID finden. 

Ich habe folgenden Code geschrieben:

private UIComponent getUIComponent(String id) {  
      return FacesContext.getCurrentInstance().getViewRoot().findComponent(id) ;  
}

Ich habe einen p:inputTextarea definiert als:

<p:inputTextarea id="activityDescription" value="#{adminController.activityDTO.activityDescription}" required="true" maxlength="120"
    autoResize="true" counter="counter" counterTemplate="{0} characters remaining." cols="80" rows="2" />

Wenn nun die Methode als getUIComponent("activityDescription") aufgerufen wird, wird null zurückgegeben. Wenn ich sie jedoch als getUIComponent("adminTabView:activityForm:activityDescription") aufrufe, kann ich die org.primefaces.component.inputtextarea.InputTextarea-Instanz abrufen. 

Gibt es eine Möglichkeit, die Komponente nur mit der ID zu erhalten, d. H. "ActivityDescription", nicht mit der absoluten ID, d.

44
Tapas Bose

Sie können den folgenden Code verwenden:

public UIComponent findComponent(final String id) {

    FacesContext context = FacesContext.getCurrentInstance(); 
    UIViewRoot root = context.getViewRoot();
    final UIComponent[] found = new UIComponent[1];

    root.visitTree(new FullVisitContext(context), new VisitCallback() {     
        @Override
        public VisitResult visit(VisitContext context, UIComponent component) {
            if(component.getId().equals(id)){
                found[0] = component;
                return VisitResult.COMPLETE;
            }
            return VisitResult.ACCEPT;              
        }
    });

    return found[0];

}

Dieser Code findet nur die erste Komponente in der Baumstruktur mit dem von Ihnen übergebenen id. Sie müssen etwas anpassen, wenn zwei Komponenten mit demselben Namen in der Baumstruktur vorhanden sind (dies ist möglich, wenn sie unter zwei verschiedenen Namenscontainern liegen).

40
Nerrve

Ich versuche diesen Code, und es hilft:

private static UIComponent getUIComponentOfId(UIComponent root, String id){
    if(root.getId().equals(id)){
        return root;
    }
    if(root.getChildCount() > 0){
        for(UIComponent subUiComponent : root.getChildren()){
                UIComponent returnComponent = getUIComponentOfId(subUiComponent, id);
                if(returnComponent != null){
                    return returnComponent;
            }
        }
    }
    return null;
}

Vielen Dank

2
Hazim

Geben Sie einfach prependId="false" in Ihr Formular ein, in dem sich dieser Textbereich befindet.

1
Darka

Vielleicht ist es nicht möglich. Die FacesContext.getCurrentInstance().getViewRoot().findComponent(id)-Methode gibt nur eine UIComponent zurück. ViewRoot ist als Baumstruktur aufgebaut. Wenn Sie also zwei Formulare in der Ansicht haben, jedes mit einer Komponente mit id="text", werden die übergeordneten Komponenten zur ID hinzugefügt, damit sie nicht in Konflikt stehen. Wenn Sie die beiden id="text"-Komponenten in dasselbe Formular einfügen, wird Java.lang.IllegalStateException ausgegeben.

Wenn Sie alle Komponenten mit der gesuchten ID suchen möchten, können Sie eine Methode schreiben, die Folgendes implementiert:

List<UIComponent> foundComponents = new ArrayList();
for(UIComponent component: FacesContext.getCurrentInstance().getViewRoot().getChildren()) {
    if(component.getId().contains("activityDescription")){
        foundComponents.add(component);
    }
}

Oder wenn Sie das erste Vorkommen suchen möchten:

UIComponent foundComponent;
for(UIComponent component: FacesContext.getCurrentInstance().getViewRoot().getChildren()) {
    if(component.getId().contains("activityDescription")){
        foundComponent = component;
        break;
    }
}
1
kauedg

Ja, in allen übergeordneten Komponenten, die NamingContainers sind, müssen Sie das Attribut prependId="false" hinzufügen - es funktioniert sicher in <h:form> und sollte in anderen funktionieren. 
Wenn es nicht möglich ist, es über ein Attribut in der .xhtml-Datei festzulegen, müssen Sie den Wert programmgesteuert festlegen.

Vorschlag nach Autorenkommentar der Frage:

Wenn ein solches Attribut in den von Ihnen verwendeten Komponenten nicht vorhanden ist, versuchen Sie die find-find-Methode wie folgt:

private UIComponent findComponent(String id, UIComponent where) {
if (where == null) {
   return null;
}
else if (where.getId().equals(id)) {
   return where;
}
else {
   List<UIComponent> childrenList = where.getChildren();
   if (childrenList == null || childrenList.isEmpty()) {
      return null;
   }
   for (UIComponent child : childrenList) {
      UIComponent result = null;
      result = findComponent(id, child);
      if(result != null) {
         return result;
   }
   return null;
}   

Als nächstes einfach aufrufen

UIComponent iamLookingFor = findComponent(myId, FacesContext.getCurrentInstance().getViewRoot());

Das wird helfen?

0
emka86