Monday, November 26, 2012

Zend Framework 1: Zend Form Display Groups

Greetings Programs,

Creating large forms with many inputs can be a challenge for your UI especially if you want to avoid scrolling the page. These days with tablets, smart tvs, and cell phones the need to create UIs that minimize scrolling is often desired. If you and your team are going to write an app for every platform out there then you probably have a pretty big team. If you don't,  don't despair, many of these platforms have a browser so if you're careful how you design your UI you might find that you can have a very nice interface across many platforms and not have to have a fleet of developers for every platform out there. 

Zend Forms and display groups are one potential way to solve this problem. In this Post we are going to create a shipping and billing address form that is split across the screen. Billing on one side and shipping on the other. We will be using form decorators to wrap display groups in a div that can be positioned using CSS. In the next post we will look at using sub forms to accomplish the same effect.

The code is available at https://github.com/jdellostritto/ZTMPL_formdisplaygroups.git


To start we need an idea of what we want this to look like...


The form above is separated in two halves based on our target design. A sample structure that will allow for what we want to accomplish can be seen below.

...
Full code for the Application_Address_Form Class can be found on github. In this form class we create functions for the inputs we need created. Because we have two nearly identical display groups we create a single function that creates our input text field based on a name we give it.  In the _render_fullname function we send an argument called $given_name. Calling $this->_render_fullname("bill_fullname") and $this->_render_fullname("ship_fullname") will result in two input elements on our form (we could further optimize our code by creating a single function that creates any text input - later). All we need to do after this is add them to two distinct display groups....

The init() function of our form helps us do just this. First we create the items we need in our form. Notice step 4 where we create duplicate inputs for both groups:
...
Second we create our groups and decorate the form. Step 7 in the code below is where we create our display groups giving the names of the elements created previously as an array, giving each group a distinct name, and finally decorating them in a structure that meets our design requirements.
...
Decorating our groups is done in the function below. Notice that we take the group name and a given_name as arguments. The group is the target display group and the given_name is a string we can use to differentiate our div id attribute:
...
The last item left on our list is to style our page to get the desired effect. This is accomplished by absolute positioning the bill group and ship group....


I have some other small tricks in this baseline that I have learned from many sources... too many to list.  There are many ways to accomplish what i have posted so please if you find the time to contribute to this code or make suggestions please do not hesitate. I have learned from many posts and other sources and I appreciate every one.  

...
Kevin Flynn: Like a man says, "There are no problems, only solutions."
...
Tron 1982

Friday, November 9, 2012

Zend Framework 1 - Zend Form Custom Error Handling

Greetings Programs!
Zend Forms... a black art?

At first it may seem but spend some time and you just might realize how powerful they are. Over the past two years I have been working with the Zend framework and have become very fond of it. It is not overly prescriptive and allows me to exercise pattern design extending it and bending it to my will. I will admit that early on zend form decorators was a major challenge. It wasn't until design and front end requirements really pushed me to see how far I could extend zend forms. After a number of big challenges I realized there's a lot you can do with zend forms and decorators.

In this blog we are going to look at a Zend form and how we control error display. In a nutshell we want to....
1: Show only a "*" next to fields that have errors. 
2: Show only one error in an error field <div> based on priority.
3: decorate the form in a <div> structure.

The real problem we are trying to solve is the potential endless diarrhea of errors that can spill out of the form onto our UI and just mess everything up. 
Code can be found here: https://github.com/jdellostritto/ZTMPL_formerrors.git

So here is what we want to see in this very simple registration form.


You will notice that the email format is incorrect above. The error message tells the user and is our first priority message. Note: the password fields are incorrect (empty) as well and the form indicates that however, we don't spill those errors messages out all over the screen.

Here is a submission with a correct email format:

Notice that the email is correct and we only see the required field error because I failed to put in either the password or the confirm password. Next I will enter a password in the password field that is too short so I expect to see a length failure.


As you can see we are walking through the process one input at time. We are not leaving the user with out cues for the fields that are invalid however, we are controlling the mess that could ensue especially if we have a form with a lot of fields and many errors.  This allows us to keep our UI 'Crispy' (ref: Crispy is term used by a front end designer I know his name is Kalim).

WHAT DECORATORS DO WE NEED TO PULL THIS OFF.

Below is the HTML structure we want to use to make this work. You should always start with a definition of you ideal structure. Don't be afraid of how complex it might look. I haven't encountered a structure I couldn't resolve with decorators and zend forms.
<form>
   
   <div class="input">
   <input type="text" name="emailaddress" id="emailaddress" value="" placewholder="email address">
   <div id="error_condition_input">zend element <ul> error</div>
   </div>

   <div class="input">
   <input type="password" name="password" id="password" value="" placeholder="choose a password">
   <div id="error_condition_input">zend element <ul> error</div>
   </div>

   <div class="input">


   <input type="password" name="confirmpassword" id="confirmpassword" value=""  placeholder="confirm password">
   <div id="error_condition_input">zend element <ul> error</div>
   </div>

   <div class="submit">
   <input type="image" name="submit_reg" id="submit"    src="/zendformsample1/public/media/img/forms/next.png" type="image">
   </div>

</form>
<div id="error_condition_form">zend form <ul> custom error</div>   

First: Notice that each input has it's own <div id="error_condition_input"><div>. This is were the "*" asterisk will show up when the input is invalidated. 

Second: notice the <div id="error_condition_form"></div> at the end after the form. This is were we will show the custom error based on a priority that we set.

DECORATING THE TOP LEVEL FORM. 
I choose to decorate the form in stages. I start simply start by calling a function in my form class to do just that (function can be found in Application_Form_Index_Register Class on github).The setDecorators function is called on the form to create our default structure. Notice that we wrap our errors in the div based on the HTML structure we defined earlier. ...
DECORATING THE INPUT BOX
In the code below we define a function that will allow us to decorate our input boxes. The code above should look familiar. Wrapping the error generated by the input is accomplished the same way it was accomplished at the form level. We then wrap the whole thing in a <div> in the last line. ...

DECORATING THE SUBMIT BUTTON IMAGE
We only have a single submit button so we decorate it when we create it. If we have more than one it would make sense to move this function out into a separate function.In the _render_submit()function setDecorators is called on the submit button wrapping it in a <div> with a class = "submit".

...


TEST FOR ERRORS
At this point we should be all 'decorated up'. Each input has a nice div element for errors as does our form. With a little CSS we can move things around and have a nice looking form (see sample CSS on github). Below you will find the code for processing and setting the errors.  ...
The code above grabs the form errors which contains a listing of all the errors from each input in the order the input presents itself on the page. Using this ordering we prioritize the capture of the error and use the setErrors function for the form which overwrites any previously set error messages and flags a failed validation. It will then return. Remember the individual input errors are preserved and each is set to display "*". For more information on how this is done you'll need to look at the class Application_Form_Index_Register and the validators that are used for each input box. Again these are available on github. 

I have some other small tricks in this baseline on github that I have learned from many sources... too many to list (css helpers, resource loading, etc.). I am also aware that there are alternate approaches and some may be more clever than mine. I am happy to learn so please comment and suggest.

...You've enjoyed all the power you've been given, haven't you. I wonder how you'd take to working in a pocket calculator...
...
End of line

Master Control Program: Tron 1982