|
Download
FAQ History |
|
API
Search Feedback |
Delegating Rendering to a Renderer
For the purpose of illustrating delegated rendering, the image map example includes an
AreaRenderer, which performs the rendering for theUIAreacomponent.To delegate rendering, you need to perform these tasks:
Create the Renderer Class
When delegating rendering to a renderer, you can delegate all encoding and decoding to the renderer, or you can choose to do part of it in the component class. The
UIAreacomponent class only requires encoding.To delegate the encoding to
AreaRenderer, the AreaRenderer needs to implement anencodeEndmethod.The encoding methods in a
Rendererare just like those in aUIComponentclass except that they accept aUIComponentargument as well as aFacesContextargument, whereas theencodeEndmethod defined byUIComponentBaseonly takes aFacesContext. TheUIComponentargument is the component that needs to be rendered. In the case of non-delegated rendering, the component is rendering itself. In the case of delegated rendering, the renderer needs to be told what component it is rendering. So you need to pass the component to theencodeEndmethod ofAreaRenderer:The
encodeEndmethod ofAreaRenderermust retrieve the shape, coordinates, and alt values stored in theImageAreamodel object that is bound to theUIAreacomponent. Suppose that theareatag currently being rendered has avalueRefattribute value of"fraA". The following line fromencodeEndgets thevalueRefvalue of"fraA"and uses it to get the value of the attribute"fraA"from the FacesContext.The attribute value is the
ImageAreamodel object instance, which contains the shape, coordinates, and alt values associated with thefraAUIAreacomponent instance.Simplifying the JSP Page describes how the application stores these values.
After retrieving the
ImageAreaobject, you render the values forshape,coords, andaltby simply calling the associated accessor methods and passing the returned values to theResponseWriter, as shown by these lines of code, which write out the shape and coordinates:writer.write("<area shape=\""); writer.write(ia.getShape()); writer.write("\"" ); writer.write(" coords=\""); writer.write(ia.getCoords());The
encodeEndmethod also renders the JavaScript for theonmouseout,onmouseover, andonclickattributes. The page author only needs to provide the path to the images that are to be loaded during anonmouseoveroronmouseoutaction:<d:area id="France" valueRef="fraA" onmouseover="/cardemo/world_france.jpg" onmouseout="/cardemo/world.jpg" />The
AreaRendererclass takes care of generating the JavaScript for these actions, as shown in this code fromencodeEnd:writer.write(" onmouseover=\""); writer.write("document.forms[0].mapImage.src='"); imagePath = (String) component.getAttribute("onmouseover"); if ('/' == imagePath.charAt(0)) { writer.write(imagePath); } else { writer.write(contextPath + imagePath); } writer.write("';\""); writer.write(" onmouseout=\""); writer.write("document.forms[0].mapImage.src='"); imagePath = (String) component.getAttribute("onmouseout"); if ('/' == imagePath.charAt(0)) { writer.write(imagePath); } else { writer.write(contextPath + imagePath); }The JavaScript that
AreaRenderergenerates for theonclickaction sets the value of the hidden variable,selectedArea, to the value of the current area's component ID and submits the page:writer.write("\" onclick=\"document.forms[0].selectedArea.value='"); writer.write(component.getComponentId()); writer.write("'; document.forms[0].submit()\""); writer.write(" onmouseover=\""); writer.write("document.forms[0].mapImage.src='");By submitting the page, this code causes the JavaServer Faces lifecycle to return back to the Reconstitute Component Tree phase. This phase saves any state information--including the value of the
selectedAreahidden variable--so that a new request component tree is constructed. This value is retrieved by thedecodemethod of theUIMapcomponent class. Thisdecodemethod is called by the JavaServer Faces implementation during the Apply Request Values phase, which follows the Reconstitute Request Tree phase.In addition to the
encodeEndmethod,AreaRendereralso contains an empty constructor. This will be used to create an instance ofAreaRendererso that it can be added to the render kit.
AreaRendereralso must implement thedecodemethod and the other encoding methods, whether or not they are needed.Finally,
AreaRendererrequires an implementation ofsupportsComponentType:public boolean supportsComponentType(String componentType) { if ( componentType == null ) { throw new NullPointerException(); } return (componentType.equals(UIArea.TYPE)); }This method returns
truewhencomponentTypeequalsUIArea's component type, indicating thatAreaRenderersupports theUIAreacomponent.Note that
AreaRendererextendsBaseRenderer, which in turn extendsRenderer. TheBaseRendererclass is included in the RI of JavaServer Faces technology. It contains definitions of theRendererclass methods so that you don't have to include them in your renderer class.Register the Renderer with a Render Kit
For every UI component that a render kit supports, the render kit defines a set of
Rendererobjects that can render the component in different ways to the client supported by the render kit. For example, the standardUISelectOnecomponent class defines a component that allows a user to select one item out of a group of items. This component can be rendered with theListboxrenderer, theMenurenderer, or theRadiorenderer. Each renderer produces a different appearance for the component. TheListboxrenderer renders a menu that displays all possible values. TheMenurenderer renders a subset of all possible values. TheRadiorenderer renders a set of radio buttons.When you create a custom renderer, you need to register it with the appropriate render kit. Since the image map application implements an HTML image map,
AreaRenderershould be registered with the HTML render kit.You register the renderer using the application configuration file (see Application Configuration):
<render-kit> <renderer> <renderer-type>Area</renderer-type> <renderer-class> components.renderkit.AreaRenderer </renderer-class> </renderer> </render-kit>The
render-kitelement represents aRenderKitimplementation. If norender-kit-idis specified, the default HTML render kit is assumed. The renderer element represents aRendererimplementation. By nesting therendererelement inside therender-kitelement, you are registering the renderer with theRenderKitassociated with therender-kitelement.The
renderer-typewill be used by the tag handler, as explained in the next section. Therenderer-classis the fully-qualified classname of theRenderer.Identify the Renderer Type
During the Render Response phase, the JavaServer Faces implementation calls the
getRendererTypemethod of the component's tag to determine which renderer to invoke, if there is one.The
getRendererTypemethod ofAreaTagmust return the type associated withAreaRenderer. Recall that you identified this type when you registeredAreaRendererwith the render kit. Here is thegetRendererTypemethod from thecardemoapplication'sAreaTagclass:
|
Download
FAQ History |
|
API
Search Feedback |
All of the material in The Java(TM) Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.