Chuyển đến nội dung chính

[CQ FORM] Validation Form in CQ

Purpose:

Provide an abstraction for managing the submission of statically defined HTML Forms.

How to Use (v1.2.2+)

To create a enable the Forms, create a new sling:OsgiConfig a OSGi component configuration:
/apps/myapp/config/com.adobe.acs.commons.forms.impl.FormsRouterImpl

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
   xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
   jcr:primaryType="sling:OsgiConfig"
   suffix="/submit/form"
/>

The property suffix will be used to identify and properly route Forms submissions.

The Form API

The Form abstraction is simple development abstraction for transporting data between the browser and AEM. The abstraction is broken into two part:
  1. The Form (Form.java) which represents the mutable Form state
  2. The FormHelpers (POST-Redirect-GET or Forward-as-GET) which contain the logic for transporting the Form data and re-constituing the Form on the other side of the HTTP Request.

Limitations

Current limitations of the Forms implmentation include:
  • Only supports transport of text/String-based data (No file uploads)
  • Multiple form parameters by the same name is not supported. A random value will be selected.
  • Multiple forms can exist on a page, however any data in the unsubmitted forms will be lost (unless you’re using XHR POSTs)

The Form

Form is a class that represents HTTP Form submission data, and contains the following data:
  • name: the form’s conceptual name; acts as a UID when multiple forms are on a page (ex. login, registration)
  • data: which holds submitted form data
  • errors: which holds error messaging associated with form field

Form Helpers

Generic Form Helper

FormHelpers interact with Form objects, transporting and re-constructing them on either side of the HTTP Request.
Most of the time the “generic” FormHelper is the better choice. This allows for very easy switching betwen the POST-Redirect-Get and Forward-as-Get implementations.

FormHelper formHelper = sling.getService(PostRedirectGetFormHelper.class);
OR
FormHelper formHelper = sling.getService(ForwardAsGetFormHelper.class);

Forward-as-GET Form Helper

The Forward Form Helper is used when Forms need to redirect (Forward-as-GET) internally to render end state of forms.
Forward Form Helper requests the target resource as an internal Synthetic GET Request, and passes the Form object as a SlingHttpServletRequest attribute.
Key features/use-cases
  • Form-payload is too large to be transferred via GET Query Params (to render error page)
  • You aren’t uncomfortable exposing for- data as clear text in query params (even though they fall under SSL envelope)
  • You don’t mind resubmitting forms when a user clicked “refresh”
  • Keeps a “clean” address bar in the browser

POST-Redirect-GET Form Helper

The POST-Redirect-GET (PRG) Form Helper is used when Forms need/can redirect externally (302) to re-render a form or success page.
PRG Form Helper requests the target resource as a 302 Redirect, serialized the Form data as JSON and transports the JSON data as GET Query Parameters. This works well when Form data is under ~2000 characters in total.
Key features/use-cases
  • Form-payload is too small-ish (< 2000 chars encoded)
  • You like a clean separation between your GET and POST requests
  • Don’t mind a messy address bar in the browser (errors are returned to form via GET QPs)
Remember: GET Query Parameters are passed WITHIN the HTTPS envelope, so they are not visible on the wire

Sample Implementation

This example used the PRGFormHelper, however this can easily be swapped out for the ForwardFormHelper;
The normalized FormHelper API that wraps common usecases in .renderForm(..) and .renderOtherForm(...) methods.
Generally these methods can be used, and PostRedirectGetFormHelper.sendRedrect(..) and ForwardAsGetFormHelper.forwardAsGet(..) can be reserved for unusual use-cases where even more control is required.

demo.jsp

Initialize the Form object with the slingRequest.
This will intelligently look for the Form data from POST Parameters, GET Query Parameters, or HttpServletRequest Attributes depending on the context and FormHelper used.
If the request is a “fresh” request to the page, the form and its errors will be empty.
Changing between Form strategies (PRG vs Fwd-as-GET) is as easy as swapping out the FormHelper as shown below.
Also, don’t forget to make them the same in post.POST.jsp;

IMPORTANT: FormHelper Services should be sync’d between the form rendering JSP and the POST handler JSP.

<%
/* FormHelper formHelper = sling.getService(PostRedirectGetFormHelper.class); */
FormHelper formHelper = sling.getService(ForwardAsGetFormHelper.class);
Form form = formHelper.getForm("demo", slingRequest);
%>
<%-- Check if the form has any errors, and display a list of all the error messages --%>

<% if(form.hasErrors()) { %>
   <h2 class="alert">Your form has errors!</h2>
<% } %>

Set the form to POST back to the component; use formHelper.getAction(..) to add the suffix that is registered with the POST handler. Defaults to /submit/form – can change via OSGi configuration on:
com.adobe.acs.commons.forms.helpers.impl.PostFormHelperImpl#prop.form-suffix
Optionally pass a second parameter to getAction() to set the selector used to resolve the script for this POST request. If not provided, defaults to “post” (to resolve to post.POST.jsp).
Useful for multi-page form wizards.

Example:

<%= formHelper.getAction(currentPage, "step1") %> will be handled by /apps/acme/components/demo/step1.POST.jsp
<form method="post" action="<%= formHelper.getAction(currentPage) %>">
   <%= formHelper.getFormInputsHTML(form) %>

   <fieldset>
       <legend>Form Demo</legend>

       <div><%= form.getError("myField") %></div>
       <label <%= form.hasError("myField") ? "class=\"error\"" : "" %>>My Field:</label>
       <input type="text" name="myField" value="<%= form.get("myField") %>"/>

       <input type="submit" value="Submit"/>
   </fieldset>
</form>


post.POST.jsp

Changing between Form strategies (PostRedirectGet vs ForwardAsGet) is as easy as swapping out the FormHelper as show below. Or for the common case, use generic FormHelper with .renderForm(..)
Choose the return-to-form method based on the Form strategy. You can use PostRedirectGetFormHelper.sendRedirect(..) or ForwardAsGetFormHelper.forwardAsGet(..) variations if the FormHelper.renderForm(..) variations are sufficient (renderForm covers the 80% usecase)
You’ll want to match currentPage/resource/path up to form.getAction(..) in demo.jsp

<%
// PostRedirectGetFormHelper formHelper = sling.getService(ForwardAsGetFormHelper.class);
// ForwardAsGetFormHelper formHelper = sling.getService(ForwardAsGetFormHelper.class);
// FormHelper formHelper = sling.getService(PostRedirectGetFormHelper.class);

FormHelper formHelper = sling.getService(ForwardAsGetFormHelper.class);

//  Get the Form
Form form = formHelper.getForm("demo", slingRequest);

// Validation should be moved to a supporting OSGi Service - placement only for illustration
if(form.get("myField") == null || form.get("myField").length() < 10) {
   form.setError("myField", "What kind of answer is: " + form.get("myField"));
}

if(form.hasErrors()) {
    formHelper.renderForm(form, currentPage, slingRequest, slingResponse);
} else {
   // Save the data; or whatever you want
   slingResponse.sendRedirect("/content/success.html");
}
%>

Ref: http://adobe-consulting-services.github.io/acs-aem-commons/features/forms.html

Nhận xét

Bài đăng phổ biến từ blog này

How to add a new supported language in CQ / WEM (Translator in CQ)

Use case:  You want to add new language to CQ Change display language options in translator grid Change language name and default countries  Solution: You can access translator UI in CQ with following URL http://<HOST>:<PORT>/libs/cq/i18n/translator.html Create new language location for Dictionary Go to CRXDE lite (or your favorite JCR browser) and add this structure (assuming /apps/myapp/i18n as a typical location for custom apps): /apps/myapp/i18n [sling:Folder]     - de [nt:unstructured]         + jcr:mixinTypes = [mix:language]         + jcr:language = de     - fr [nt:unstructured]         + jcr:mixinTypes = [mix:language]         + jcr:language = fr Then reload the translator and the path /apps/ myapp /i18n should show up in the drop-down at the top. Note: the translator will only save translations for languages that are actually present underneath the path (e.g. /apps/myapp/i18n), others will be skipped. Then on jsp pa

Login / Logout on a Publish instance and Closed User Group (CUG)

In CQ5 there is the login logout could be configured using a Closed User Group. Closed User Groups (CUGs) are used to limit access to specific pages that reside within a published internet site. Such pages require the assigned members to login and provide security credentials. http://dev.day.com/docs/en/cq/5-4/howto/create_apply_cug.html The logout using /libs/cq/core/content/login.logout.html always gets redirected to the geometrixx site   http://localhost:4503/content/geometrixx-outdoors/en.html By configuring the Default login page  under the osgi configuration for com.day.cq.auth.impl.LoginSelectorHandler to be – /content/mysite/en/login But still after logout the page goes to the geometrixx site. IIRC, the redirect first goes to to / which then goes through the standard, somewhat complex handling of the root with multiple redirects: 1) / has a resource type of sling:redirect and redirects to /index.html 2) /index.html is handled by the RootMappingServlet [0] which h

[PERFORMANCE] Adobe WEM/CQ performance tuning

Adobe WEM/CQ performance tuning Contents Caching-related configurations CRX Bundle cache CRX Search index handler (Lucene) cache Tar PM index cache Scalability Maintenance Optimizing Tar Files (for Tar Persistence Manager) Data Store Garbage Collection Main documentation you should consult first: http://dev.day.com/docs/en/cq/current/deploying/performance.html http://dev.day.com/content/kb/home/cq5/CQ5Troubleshooting/performancetuningtips.html Caching-related configurations CRX Bundle cache CRX caches bundles, consisting of a node with all its properties. This is used by all bundle-based Persistence Managers. The default size of BundleCache is 8 MB. If this is too small it can cause an excessive number of read-accesses to the underlying persistence layer. Set the bundleCacheSize to something larger than the default. See more here: http://dev.day.com/docs/en/cq/current/deploying/performance.html#CRX%20Bundle%20Cache CRX Search index handler (Lucene