Search code examples
jsfeditconditional-rendering

How to build "edit" button in JSF and switch between h:outputText and h:inputText


How can I create an "edit" button so that when the button is clicked it will change the h:outputText to h:inputText?


Solution

  • Make use of the rendered attribute:

    <h:outputText value="#{bean.entity.property}" rendered="#{not bean.editmode}" />
    <h:inputText value="#{bean.entity.property}" rendered="#{bean.editmode}" />
    ...
    <h:commandButton value="Edit" action="#{bean.edit}" rendered="#{not bean.editmode}" />
    <h:commandButton value="Save" action="#{bean.save}" rendered="#{bean.editmode}" />
    

    With this in a view scoped bean:

    private boolean editmode;
    
    public void edit() {
        editmode = true;
    }
    
    public void save() {
        entityService.save(entity);
        editmode = false;
    }
    
    public boolean isEditmode() {
        return editmode;
    }
    
    // ...
    

    Note that the bean being view scoped is important for the reason mentioned in point 5 of this answer: commandButton/commandLink/ajax action/listener method not invoked or input value not updated.


    Alternatively, you can use the disabled attribute on input component in combination with a shot of CSS which basically makes it look like an output component (by removing the border).

    <h:inputText value="#{bean.entity.property}" disabled="#{not bean.editmode}" />
    ...
    <h:commandButton value="Edit" action="#{bean.edit}" rendered="#{not bean.editmode}" />
    <h:commandButton value="Save" action="#{bean.save}" rendered="#{bean.editmode}" />
    

    with e.g.

    input[disabled] {
        border: 0;
    }
    

    Also here, the bean must be view scoped. See also How to choose the right bean scope?