简体   繁体   中英

How to reference 'this' from a javascript call in a JSF component?

    <h:commandLink id="#{id}" value="#{value}" action="#{actionBean.getAction}" onclick="alert(this);"/>

In the previous simplified example, the 'this' keyword used in the Javascript function won't reference the generated A HREF element, but will reference to the global window, because JSF generates the following (simplified) code:

<a onclick="var a=function(){alert(this)};var b=function(){if(typeof jsfcljs == 'function'){jsfcljs(document.forms['mainForm'],'generatedId,action,action','');}return false};return (a()==false) ? false : b();" href="#" id="generatedId">text</a>

So because JSF wraps the user defined onclick in a function, this will point to the global window. I don't have access to the id of the element because my code is used in a generic component that can be used in loops etc. and I don't use backing beans (Facelets + JSF).

So my question is, is there a way to access the A HREF element from within my onclick javascript function, without knowing the id?

var a=function(){alert(this)};var b=function(){if(typeof jsfcljs == 'function'){jsfcljs(document.forms['mainForm'],'generatedId,action,action','');}return false};return (a()==false) ? false : b();

Oh dear lord! That's violently horrible.

And no, it appears to be throwing away 'this' before you get a chance to look at it - it should have said "return (a.call(this)==false)? false : b()".

On IE only you could read the srcElement from window.event, but that's pretty ugly.

How about avoiding JSF's weird event mangling entirely, by using unobtrusive scripting? eg. omit the onclick and say:

document.getElementById('generatedId').onclick= function() {
    alert(this);
    return false; // if you want to not follow the link
}

If you need the link to continue into JSF's event handling, you'd have to save the old onclick event handler and call it at the end of the function, or use Element.addEventListener (attachEvent on IE) to put your scripting hooks in at an earlier stage than the onclick.

EDIT:

Go here for a small library/sample code for getting the clientId from the id : JSF: working with component IDs


The HTML ID emitted by JSF controls is namespaced to avoid collisions (eg the control is a child of UIData and emitted multiple times, or the container is a portlet so the view can be rendered multiple times in one HTML page). This ID is known as the clientId, and is distinct from the ID set on the JSF control.

If you want to emit the clientId in the view, you can use a managed bean to do it.

public class JavaScriptBean {

    public String getOnclickButton1() {
        String id = "button1";
        String clientId = getClientId(id);
        return "alert('You clicked element id=" + clientId + "');";
    }

    public String getOnclickButton2() {
        String id = "button2";
        String clientId = getClientId(id);
        return clientId;
    }

    private String getClientId(String id) {
        FacesContext context = FacesContext.getCurrentInstance();
        UIViewRoot view = context.getViewRoot();
        UIComponent component = find(view, id);
        return component.getClientId(context);
    }

    private UIComponent find(UIComponent component, String id) {
        if (id.equals(component.getId())) {
            return component;
        }

        Iterator<UIComponent> kids = component.getFacetsAndChildren();
        while (kids.hasNext()) {
            UIComponent kid = kids.next();
            UIComponent found = find(kid, id);
            if (found == null) {
                continue;
            }
            return found;
        }

        return null;
    }

}

This is configured in the application's faces-config.xml and bound to the view using the expression language:

<f:view>
    <h:form>
        <h:commandButton id="button1" value="b1"
            onclick="#{javaScriptBean.onclickButton1}" />
        <h:commandButton id="button2" value="b2"
            onclick="alert('You clicked element id=#{javaScriptBean.onclickButton2}');" />
    </h:form>
</f:view>
<head>
..
<script type="text/javascript">
var myCommandLinkId = "undefined";
</script>
..
</head>

..

<h:commandLink id="myCommandLink" value="Click Me" onmousedown="myCommandLinkId=this.id;" onclick="alert(myCommandLinkId);" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM