Update of /cvsroot/struts/struts-site/src/documentation/content/xdocs/strutsdialogs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7826/src/documentation/content/xdocs/strutsdialogs Modified Files: dialogaction.xml index.xml selectaction-sample.xml selectaction.xml Log Message: Index: dialogaction.xml =================================================================== RCS file: /cvsroot/struts/struts-site/src/documentation/content/xdocs/strutsdialogs/dialogaction.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** dialogaction.xml 5 Jul 2005 07:54:01 -0000 1.5 --- dialogaction.xml 22 Jul 2005 01:38:00 -0000 1.6 *************** *** 83,116 **** </section> - <section id="keysandmappings"> - <title>Default keys and mappings</title> - <p>DialogAction defines several event keys and method mappings. - See <link href="selectaction.html">SelectAction</link> for - explanation of event dispatching.</p> - - <!-- - <p>String DIALOG-VIEW-KEY = "DIALOG-VIEW";<br/> - This is a default view mapping, mandatory if a dialog action has only one page to render. - If dialog can render different pages depending on application state, use action-specific mappings.</p> - - <p>String DIALOG-RELOAD-KEY = "DIALOG-RELOAD";<br/> - This is a default reload mapping, optional. Can be omitted if a dialog action redirects to itself - for view processing, which is a default behavior. It is possible to split input and output processing - between two separate actions, in this case use this mapping to set the "view action" name. - </p> - --> - <p>String DIALOG-EVENT-KEY = "DIALOG-EVENT";<br/> - This is a default prefix for all submit events.</p> - - <p>String DIALOG-EVENT-INIT = "<strong>DIALOG-EVENT</strong>-INIT";<br/> - This is a default name of initialization key. It is important that initialization key - is based on the event key.</p> - - <p>The standard keys and output mappings are defined in <code>DialogConstants</code> class.</p> - </section> - <section id="usage"> <title>Usage</title> ! <p>When form is submitted, DialogAction dispatches submit event to a corresponding handler method. To make this happen, automatic validation must be turned off in a corresponding form bean. The hander should validate input data explicitly, and perform model update if needed.</p> --- 83,95 ---- </section> <section id="usage"> <title>Usage</title> ! <p>When an action is loaded either with hyperlink or by typing its location in the browser address ! field, browser sends GET request to the server. When DialogAction receives GET request, which does ! not contain event parameter, it renders a page. In case of simple dialogs, this would be default view. ! In case of multi-page component, this would be a page, corresponding to current component state. ! The page usually contains HTML form, which accepts user data.</p> ! ! <p>When form is submitted, DialogAction dispatches browser event to a corresponding handler method. To make this happen, automatic validation must be turned off in a corresponding form bean. The hander should validate input data explicitly, and perform model update if needed.</p> *************** *** 120,124 **** because request for data submission has POST type, while redirected request for action reloading is automatically converted to GET type. GET request does not cause component reloading. ! Instead, when DialogAction receives GET request, it renders a view.</p> <source> --- 99,105 ---- because request for data submission has POST type, while redirected request for action reloading is automatically converted to GET type. GET request does not cause component reloading. ! Instead, when DialogAction receives GET request, it renders a view, corresponding to current ! state. The lifecycle repeats until the component decides to hand control over to another ! component, usually when user input does not contain errors.</p> <source> *************** *** 126,143 **** ... <forward name = "DIALOG-RELOAD" path="/dialogloginaction.do" redirect="true"/> ! <forward name="DIALOG-VIEW" path="/dialogloginaction.jsp"/> </action> </source> <p>If no errors were detected and action can render a view for new component state, ! then component can be reloaded. Otherwise, control is handed over to another action. Redirection ! is a preferred way to hand over the control to prevent double submit issues.</p> <p>When a user refreshes a page, component reloads itself, and displays a view appropriate to its state. This implies that application state must be stored on server between requests. The view is rendered by <code>getView</code> method. For a simple web dialog, which has only one ! view, the default implementation of getView is sufficient, it returns "DIALOG-VIEW" mapping. ! All you need is define a name of JSP page in the <code>struts-config.xml</code> file. See example ! above.</p> <p>Do not use redirection for a view. If you create more complex web component --- 107,125 ---- ... <forward name = "DIALOG-RELOAD" path="/dialogloginaction.do" redirect="true"/> ! <forward name = "DIALOG-VIEW" path="/dialogloginaction.jsp"/> </action> </source> <p>If no errors were detected and action can render a view for new component state, ! then component can either reload itself, or hand control over to another action. Redirection ! is a preferred way to hand over the control to prevent double submit issues. ! DialogAction has default mapping name, used for component reloading: "DIALOG-RELOAD".</p> <p>When a user refreshes a page, component reloads itself, and displays a view appropriate to its state. This implies that application state must be stored on server between requests. The view is rendered by <code>getView</code> method. For a simple web dialog, which has only one ! view, the default implementation of getView is sufficient. All you need is define a name of ! JSP page in the <code>struts-config.xml</code> file, which corresponds to default "DIALOG-VIEW" ! mapping. See example above.</p> <p>Do not use redirection for a view. If you create more complex web component *************** *** 145,160 **** mapping for each component state.</p> ! <p>A special init key parameter must be used to initialize and reset DialogAction. ! This is necessary because otherwise there would be no way to distinguish the following events:</p> <ul> ! <li>use the component with fresh set of data;</li> ! <li>navigate to component using a link;</li> <li>refresh a component explicitly;</li> <li>automatically reload a component as the second phase of input processing.</li> </ul> ! <p>Initialization event allows to reset the component for new set of data. Three ! other events: linking, refreshing and component reloading are treated the same, and ! render a view, corresponding to current component state. That means that navigating ! to a component via link displays current state of component, but does not initialize it.</p> </section> --- 127,149 ---- mapping for each component state.</p> ! <p>DialogAction has an option to reset the component when it receives new portion ! of data submitted with POST request. POST request method signals that browser submits new ! data instead of loading existing information. But sometimes component has to be reset with ! GET method, if it is navigated using hyperlink. DialogAction needs to distinguish these ! situations:</p> <ul> ! <li>reset component and fill it with new data;</li> ! <li>navigate to component using a "clean" link;</li> <li>refresh a component explicitly;</li> <li>automatically reload a component as the second phase of input processing.</li> </ul> ! <p>DialogAction uses event parameter as flag for component that it can be reset. ! Three other situations: "clean" linking, refreshing and component reloading are ! treated the same, because request does not contain event parameter in all three cases. In these ! cases DialogAction renders a view, corresponding to current component state.</p> ! ! <p>In plain words the above means that navigating to a component via link, which does not ! have event key as query parameter, displays current state of component but does not initialize ! it. See live demos for details, and pay attention to component URLs.</p> </section> Index: index.xml =================================================================== RCS file: /cvsroot/struts/struts-site/src/documentation/content/xdocs/strutsdialogs/index.xml,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** index.xml 11 Jul 2005 07:46:53 -0000 1.8 --- index.xml 22 Jul 2005 01:38:00 -0000 1.9 *************** *** 9,19 **** <section id="overview"> <title>Overview</title> ! <p>Struts Dialogs library allows building <em>web components</em>, ! <em>web controls</em> and <em>web dialogs</em>, using Struts and JSP.</p> <p><strong>Web component</strong> is a server-side object, which is:</p> <ul> <li>stateful;</li> ! <li>can process input events</li> <li>can render itself according to its current state;</li> </ul> --- 9,18 ---- <section id="overview"> <title>Overview</title> ! <p>Struts Dialogs library allows building <em>web components</em> using Struts and JSP.</p> <p><strong>Web component</strong> is a server-side object, which is:</p> <ul> <li>stateful;</li> ! <li>can process input events;</li> <li>can render itself according to its current state;</li> </ul> *************** *** 21,25 **** <p><strong>Web control</strong> is a web component, which:</p> <ul> ! <li>can be embedded into a complex <em>master page</em>;</li> <li>can interact with master page and, optionally, with other web controls.</li> </ul> --- 20,24 ---- <p><strong>Web control</strong> is a web component, which:</p> <ul> ! <li>can be embedded into a <em>master page</em>;</li> <li>can interact with master page and, optionally, with other web controls.</li> </ul> *************** *** 30,44 **** <p>If the above definition sounds too vague and generic, think of a standard login form. It asks a user for name and password. If entered information is incorrect, login form ! redisplays itself along with error message. Therefore, login form is an example of a ! <em>login dialog</em>. It renders itself, it has only one view, and it ! is stateful, because if you reload login page, it retains username and password.</p> <p>Now consider a component which not only collects username and password, but also ! keeps track of user login/logout status. This would be a <em>login component</em>. ! It is more complex than a login dialog, because it maintains two states and ! two corresponding views: "not logged in" and "logged in". After user successfully logs ! in, login component displays page corresponding to "logged in" state, which shows ! user information. This is a stateful component, because it shows user information ! page whenever a logged-in user navigates to login component.</p> <p>What if we want to embed login component in a complex web page? For example, see --- 29,44 ---- <p>If the above definition sounds too vague and generic, think of a standard login form. It asks a user for name and password. If entered information is incorrect, login form ! redisplays itself along with error message. Login form can render itself, it has only ! one view, and it is stateful, because if you reload login page, it retains username and ! password. Therefore, login form is an example of a ! <link href="http://www.superinterface.com/strutsdialog/logindialog.html">login dialog</link>.</p> <p>Now consider a component which not only collects username and password, but also ! displays user's login/logout status. It is more complex than a login dialog, because ! it maintains two states and two corresponding views: "not logged in" and "logged in". ! This is a <link href="http://www.superinterface.com/strutsdialog/logincomponent.html">login component</link>. ! After user successfully logs in, login component displays page corresponding to "logged in" ! state, which shows user information. Whenever logged-in user navigates to this component, ! the latter shows user's information.</p> <p>What if we want to embed login component in a complex web page? For example, see *************** *** 46,50 **** There is a small login form in the upper right corner of the home page. After you log in, the content of the form changes and shows your login name and logout button. This ! login form, embedded into master page, is an example of <em>login control</em>.</p> </section> --- 46,51 ---- There is a small login form in the upper right corner of the home page. After you log in, the content of the form changes and shows your login name and logout button. This ! login form, embedded into master page, is an example of ! <link href="http://www.superinterface.com/strutsdialog/logincontrol.html">login control</link>.</p> </section> *************** *** 55,61 **** library. SelectAction has the following features:</p> <ul> ! <li>works uniformly with pushbuttons and with image buttons;</li> ! <li>Uses <code>name</code> attribute of <code><html:button></code> tag instead of <code>value</code> ! attribute, so button caption can be set to any arbitrary value, and can be changed at runtime.</li> </ul> </section> --- 56,61 ---- library. SelectAction has the following features:</p> <ul> ! <li>works uniformly with pushbuttons, image buttons and regular links;</li> ! <li>allows to set arbitrary button caption and to change it at runtime.</li> </ul> </section> *************** *** 63,68 **** <section id="dialogaction"> <title>DialogAction: handles component state and renders a view</title> ! <p><link href="dialogaction.html">DialogAction</link> adds the following capabilities to ! event dispatching features of SelectAction:</p> <ul> <li>processing of initialization event;</li> --- 63,73 ---- <section id="dialogaction"> <title>DialogAction: handles component state and renders a view</title> ! <p><link href="dialogaction.html">DialogAction</link> allows creating robust ! web components and web controls, which enhibit ! friendly user experience, react properly to Refresh, Back and Forward buttons, ! and do not cause implicit double submits or annoying POSTDATA messages.</p> ! ! <p><code>DialogAction</code> adds the following capabilities to event dispatching ! features of SelectAction:</p> <ul> <li>processing of initialization event;</li> *************** *** 72,79 **** <li>two-phase input processing (using POST-redirect-GET pattern)</li> </ul> - - <p>DialogAction allows creating robust web components and web controls, which enhibit - friendly user experience, react properly to Refresh, Back and Forward buttons, - and do not cause implicit double submits or annoying POSTDATA messages.</p> </section> --- 77,80 ---- *************** *** 82,91 **** <title>CRUDAction: simplifies CrUD operations</title> <p><link href="crudaction.html">CRUDAction</link> is a more specific kind of action class, ! which implements all operations needed to manipulate a business object (BO), also called an ! <code>item</code>: create new item, duplicate existing item, edit, view and delete item.</p> <p>A very common use case is browsing a list of items, then selecting one item and performing ! different CRUD operations on it. CRUDAction can handle this use case with grace. It can implement ! handling of both item list and CRUD operations as one web component.</p> </section> --- 83,93 ---- <title>CRUDAction: simplifies CrUD operations</title> <p><link href="crudaction.html">CRUDAction</link> is a more specific kind of action class, ! which implements all operations needed to manipulate business data, nested business object (BO), ! or nested value object (VO) also called an <code>item</code>. This action allows to create ! new item, duplicate existing item, edit, view, clear and delete item.</p> <p>A very common use case is browsing a list of items, then selecting one item and performing ! different operations on it. CRUDAction can handle this use case with grace. It is possible to ! implement handling of both item list and CRUD operations as one web component.</p> </section> Index: selectaction-sample.xml =================================================================== RCS file: /cvsroot/struts/struts-site/src/documentation/content/xdocs/strutsdialogs/selectaction-sample.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** selectaction-sample.xml 11 Jul 2005 07:42:35 -0000 1.4 --- selectaction-sample.xml 22 Jul 2005 01:38:00 -0000 1.5 *************** *** 35,40 **** protected Map getKeyMethodMap() { Map map = new HashMap(); ! map.put("app-submit-button-add", "add"); ! map.put("app-submit-button-delete", "delete"); return map; } --- 35,40 ---- protected Map getKeyMethodMap() { Map map = new HashMap(); ! map.put(getInitKey()+"-ADD", "add"); ! map.put(getInitKey()+"-DELETE", "delete"); return map; } *************** *** 91,101 **** <action-mappings> <action path="/selectaction" ! type = "org.superinterface.samples.struts.selectaction.SelectActionTest" ! name = "dummyForm" ! scope = "request" ! parameter = "app-submit"> <forward name = "addpage" path="/selectadd.html"/> <forward name = "deletepage" path="/selectdelete.html"/> - <forward name = "cancelpage" path="/selectcancel.html"/> <forward name = "unspecifiedpage" path="/selectunspecified.html"/> </action> --- 91,98 ---- <action-mappings> <action path="/selectaction" ! type = "acme.SelectActionTest" ! name = "dummyForm"> <forward name = "addpage" path="/selectadd.html"/> <forward name = "deletepage" path="/selectdelete.html"/> <forward name = "unspecifiedpage" path="/selectunspecified.html"/> </action> *************** *** 113,120 **** <form action="http://localhost:8080/strutsdialog/selectaction.do" method="post"> ! <input type="submit" name="app-submit-button-add" value="Add button" /><br><br> ! <input type="submit" name="app-submit-button-delete" value="Delete button fancy caption" /><br><br> ! <input type="submit" name="app-submit-button-unk" value="No corresponding handler (exception)" /><br><br> ! <input type="submit" name="no-prefix" value="Does not start with prefix (unspecified)" /> </form> --- 110,117 ---- <form action="http://localhost:8080/strutsdialog/selectaction.do" method="post"> ! <input type="submit" name="DIALOG-EVENT-ADD" value="Add button" /><br><br> ! <input type="submit" name="DIALOG-EVENT-DELETE" value="Delete button fancy caption" /><br><br> ! <input type="submit" name="DIALOG-EVENT-unknown" value="No corresponding handler (exception)" /><br><br> ! <input type="submit" name="some-garbage" value="Does not start with prefix (unspecified)" /> </form> Index: selectaction.xml =================================================================== RCS file: /cvsroot/struts/struts-site/src/documentation/content/xdocs/strutsdialogs/selectaction.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** selectaction.xml 29 Jun 2005 22:51:33 -0000 1.3 --- selectaction.xml 22 Jul 2005 01:38:00 -0000 1.4 *************** *** 9,34 **** <section id="overview"> <title>Overview</title> ! <p>SelectAction is an abstract <strong>Action</strong> that dispatches an HTTP form submission event ! to a handler method. This class is an extension of standard DispatchAction and has the following ! features:</p> <ul> ! <li>works uniformly with pushbuttons and with image buttons;</li> ! <li>Uses <code>name</code> attribute of <code><html:button></code> tag instead of <code>value</code> ! attribute, so button caption can be set to any arbitrary value, and can be changed at runtime.</li> </ul> ! <p>The concrete subclass of SelectAction must define a map, which correlates submit button names with ! method names. The subclass must also define the handler methods themselves. Each method must have ! the same signature as <code>Action.execute</code> method. Subclass should not redefine <code>execute</code> ! method.</p> ! <p>Using <code>name</code> attribute has a flip side: during reset/populate/validate process, ! Struts assigns request values to corresponding properties of a form bean. Thus, button keys must be ! named differently from the properties of a form bean. Also, the dispatch action must recognize situation ! when no submit buttons were activated.</p> ! <p>Therefore, all submit buttons use a prefix in their name. The prefix is specified by <code>parameter</code> ! property of the ActionMapping. Make sure that you do not use periods in the prefix and in actual button names, ! or Struts will try to search and set the nested property of a form bean, and will likely throw an exception.</p> </section> --- 9,48 ---- <section id="overview"> <title>Overview</title> ! <p><code>SelectAction</code> is an abstract Struts <strong>Action</strong> ! that dispatches a browser event to a handler method. This class allows ! to process a form submission using either regular submit button or an image ! button. It works with regular links as well.</p> ! <ul> ! <li>Processes submit events (POST) or link events (GET).</li> ! <li>Handles pushbuttons, image buttons and regular links in ! universal fashion.</li> ! <li>Does not use <code>parameter</code> attribute of action mapping.</li> ! <li>Allows to set an arbitrary caption for a pushbutton.</li> ! <li>Button caption can be easily changed at runtime.</li> </ul> + </section> ! <section id="details"> ! <title>Technical Details</title> ! <p>Unlike <code>DispatchAction</code> and <code>LookupDispatchAction</code> ! classes, which correlate <code>value</code> attribute of <code>submit</code> ! form element with name of a handler method, this class uses <code>name</code> ! attribute. This allows to display a user-friendly caption on a submit button ! and to change button caption without redeployment.</p> ! <p>The subclass must define a map, which correlates event names with method ! names, and handler methods themselves. Events names must be different from ! names of action form properties. Each method must have the same signature ! as <code>execute</code> method.</p> ! <p>By definition, an event is a request parameter, which starts from ! a known prefix. The prefix is specified in <code>getInitKey</code> method ! and can be redefined in a subclass. Default prefix is "DIALOG-EVENT".</p> ! ! <p>If you decide to redifine the event prefix, make sure that it does not ! contain periods. Also, do not use periods for specific event names. Struts ! may throw an exception taking the name for nested property and trying ! to set its value.</p> </section> *************** *** 37,94 **** <section id="example"> <title>Usage</title> ! <p>The action should be configured in <code>struts‑config.xml</code> ! file like this:</p> ! ! <source> ! <action path="/test" ! type="org.example.MyAction" ! parameter="<strong>myapp-submit</strong>"</source> ! ! <p>where:</p> ! ! <ul> ! <li><code>org.example.MyAction</code> extends <code>SelectAction</code>;</li> ! <li><code>parameter</code> contains prefix of your choice for all submit buttons on an HTML form.</li> ! </ul> ! ! <p>The names of submit elements should start from the aforementioned prefix, for example:</p> ! ! <source> ! <form action="http://myhost/myapp/test.do" method="post"> ! <input type="submit" name="<strong>myapp-submit</strong>-button-add" value="Add button"/> ! <input type="submit" name="<strong>myapp-submit</strong>-button-delete" value="Fancy Delete button"/> ! <input type="image" name="<strong>myapp-submit</strong>-button-login" src="login.gif" value="Log In"/> ! ! </form> ! </source> ! ! <p>The concrete subclass of SelectAction class must implement <code>getKeyMethodMap</code> method, ! which defines mapping from button names to method handlers, like this:</p> ! ! <source> ! protected Map getKeyMethodMap() { ! Map map = new HashMap(); ! map.put("<strong>myapp-submit</strong>-button-add", "add"); ! map.put("<strong>myapp-submit</strong>-button-delete", "delete"); ! map.put("<strong>myapp-submit</strong>-button-login", "login"); ! return map; ! }</source> ! ! <p>Notice, that above mapping is different from <code>LookupDispatchAction</code> mapping, because no ! property files are involved, and button caption can be changed without rebuilding an application.</p> ! <p>The subclass also must implement the handler methods, for example, this is a login method ! handler:</p> ! <source> ! public ActionForward login(ActionMapping mapping, ! ActionForm form ! HttpServletRequest request, ! HttpServletResponse response) ! throws IOException, ServletException { ! // do login return mapping.findForward("success"); ! }</source> </section> --- 51,94 ---- <section id="example"> <title>Usage</title> ! <p>To use <code>SelectAction</code>, subclass it, implement <code>getKeyMethodMap</code> ! method, and map specific events to method handlers. Event name must start ! with event prefix:</p> ! <source> ! protected Map getKeyMethodMap() { ! Map map = new HashMap(); ! map.put(getInitKey()+"-ADD", "add"); ! map.put(getInitKey()+"-DELETE", "delete"); ! map.put(getInitKey()+"-CREATE", "create"); ! map.put(getInitKey()+"-LOGIN", "login"); ! return map; ! } ! </source> ! <p>Remember that standard <code><html:cancel/></code> button is implicitly ! mapped to <code>cancelled</code> method. You need to implement this method ! to receive cancel events.</p> ! <p>Implement handler methods themselves, for example:</p> ! <source> ! public ActionForward add(ActionMapping mapping, ! ActionForm form, ! HttpServletRequest request, ! HttpServletResponse response) ! throws IOException, ServletException { ! // do add return mapping.findForward("success"); ! } ! </source> + <p>Use event names in <code>name</code> attribute of submit buttons, or + as query paramter for regular links:</p> + <source> + <form action="/selecttest.do" method="post"> + <input type="submit" name="<strong>DIALOG-EVENT</strong>-ADD" value="Add item"/> + <input type="submit" name="<strong>DIALOG-EVENT</strong>-DELETE" value="Delete item"/> + </form> + <input type="image" name="<strong>DIALOG-EVENT</strong>-LOGIN" src="login.gif" value="Log In"> + <a href="/selecttest.do?<strong>DIALOG-EVENT</strong>-CREATE">Create item</a> + </source> </section> *************** *** 96,100 **** <title>Notes</title> <ul> ! <li>Subclass should not redefine <code>execute</code> method.</li> <li>If duplicate values exist for the keys returned by <code>getKeyMethodMap</code>, the first one will be returned. If no corresponding key is found then an exception will be thrown.</li> --- 96,100 ---- <title>Notes</title> <ul> ! <li>Subclass does not have to redefine <code>execute</code> method.</li> <li>If duplicate values exist for the keys returned by <code>getKeyMethodMap</code>, the first one will be returned. If no corresponding key is found then an exception will be thrown.</li> |