3
votes

I'm working at a jsf application that at a certain time need to open an external page in a new tab, leaving the first page active. I need to find a way to make the application perform, in a single button click:

  1. a redirect to an external URL in a new tab
  2. an action which disables the button itself in the original page

I've tried using an <outputLink /> but it has no action attribute. I've tried using a <commandLink />but it's unable to redirect outside. I've also tried a <commandLink /> with target="_blank" and a redirection coded in the backing bean:

<h:commandLink onclick="submit();" target="_blank" action="#{myBean.execute}" disabled="#{myBean.linkDisabled}" value="external link" />

and, in the backing bean:

public String execute() {
    linkDisabled = true;

    try{
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        externalContext.redirect(Constants.EXTERNAL_URL);
    } catch(Exception e){
        throw new FacesException("Redirection failed");
    }

    return THIS_PAGE;
}

A page is opened in a new tab but it's the current page instead of the that with URL Constants.EXTERNAL_URLand the button is still enabled. No error message is shown. Any suggestion?

Thanks in advance, Andrea

2

2 Answers

12
votes

Your question is confusing. You're mixing "link" and "button". You basically need to disable the element in the client side by JavaScript because the response does not return to the current browser window/tab, but to a different browser window/tab. In JavaScript, it's easy to disable a button, but not a link. For simplicity, I'll assume that you mean and can use a <h:commandButton> and that this is the only button in the current form.

To solve your problem, you need to remove onclick="submit()" (because it's disturbing the default behaviour) and you need to remove the navigation outcome (it should not matter, but you never know in some JSF impls) and you need to disable the button by JS in the client side.

All with all your code should look just like this:

<h:form target="_blank">
    <h:commandButton
        value="external" 
        action="#{myBean.execute}" 
        onclick="setTimeout('document.getElementById(\'' + this.id + '\').disabled=true;', 50);" />
</h:form>

And

public void execute() throws IOException {
    FacesContext.getCurrentInstance().getExternalContext().redirect(Constants.EXTERNAL_URL);
}

The setTimeout() is necessary because the button is otherwise disabled before the form data is sent which would cause that the button's own name=value pair won't be sent as request parameter and so JSF won't invoke any action.

0
votes

why don't you use action="someaction" and map it in faces-config.xml to go to another page?