DluTwBootstrap updated to ZF2 RC3
DluTwBootstrap – the Zend Framework 2 module for generating Twitter Bootstrap UI (forms) has been updated to Zend Framework 2 RC3.
About
DluTwBootstrap is a Zend Framework 2 module consisting primarily of view helpers, which let you easily generate Twitter Bootstrap UI forms from your standard Zend Framework 2 Form objects without getting your hands dirty with Twitter Bootstrap mark-up.
Reworked from scratch
The module has been updated to reflect the changes in Zend Framework 2 RC3. There are numerous BC breaks, so please refactor your projects. The Zend Framework 2 API should be changing much less now as we are approaching the stable release, so the DluTwBootstrap module should be now also more stable and should not be that picky about the ZF2 version.
Yes, the much asked for
echo $form;is here (well, not exactly that but a one-liner nonetheless).
The module has been not only updated to the latest ZF2 release, but also reworked from gound up so it is much cleaner and consistent now.
First go to on-line demo
As always, you should first visit the on-line demo here:
http://apps.zfdaily.com/dlutwbootstrap-demo
The on-line demo shows everything the module can do side-by-side with the source used to produce the demo output. The demo application is your primary reference.
Components
- DluTwBootstrap module – a ZF2 module containing view helpers, classes and styles which enable your applications to render Twitter Bootstrap UI (forms).
- DluTwBootstrap Demo module – a ZF2 module demonstrating capabilities of the DluTwBootstrap module. Install and enable this module in your app to check that you have installed DluTwBootstrap correctly.
- DluTwBootstrap Demo Application (on-line) – a simple ZF2 application integrating both the modules. You should not need the app’s source, but it’s here for your reference.
Installation
The installation steps are described in README.md files in the root of each package. Go to the respective repositories mentioned above to review them.
Usage
First of all: Yes, the much asked for echo $form; is here (well, not exactly that but a one-liner nonetheless). Although Zend Framework 2 itself does not support form display with a single command I decided to implement this feature with the following disclaimer:
The one-liner should be used only either for a quick form preview or in situations when there are no special requirements for form presentation. If you need anything else, use the manually controlled form output DluTwBootstrap offers.
So you can have it both ways. Either a dead simple fully automated form display on one line or a more laborous fully controlled form output. Your call.
The simplest case
- Create a standard
Zend\Form\Formobject - Pass your form object to view
- Prepare your form:
$form->prepare(); - Output the form:
echo $this->formTwb($form);
This procedure would output a horizontal Twitter Bootstrap form. The horizontal form type is considered default in DluTwBootstrap. Pass second argument to the formTwb() helper to control which form type will be displayed. Use the provided constants:
echo $this->formTwb($form, \DluTwBootstrap\Form\FormUtil::FORM_TYPE_VERTICAL);
There is also the third optional parameter to formTwb() which contains the display options. You can use it to change the most common display aspects of the form (e.g. the size of input fields) and still use the simple one line form output. The display options also control which fields will be marked as required (more on that later). Please go to the on-line demo to see how the $displayOptions parameter is used.
The not so simple case
If you need more control over your form presentation, your best friend is the formRowTwb() view helper. It’s used like this:
echo $this->formTwb()->openTag($form, $formType);
echo $this->formRowTwb($form->get('myElement'), $formType, $elementDisplayOptions);
echo $this->formTwb()->closeTag();
This sequence of commands would output a single form element together with label, hint, description, possible validation errors and any required Twitter Bootstrap mark-up. The formRowTwb() helper can render any supported form element (inputs, checkboxes, buttons, etc.).
This is the optimal level of control. You can insert anything special between form elements yet you still do not have to think about Twitter Bootstrap markup. Just output any number of formRowTwb() interspersed with your custom display code, wrap everything in opening/closing tags and you are done.
As for the level of control, you can go in both directions from here. You can output whole fieldsets using
echo $this->formFieldsetTwb($fieldset, $formType, $fieldsetDisplayOptions);
or you can dig deeper and manually control the individual parts of the formRow using the appropriate view helpers for label, element, description, errors, etc. In this case though you are the one who is responsible for proper Twitter Bootstrap mark-up and your forms may not render correctly if you mess things up.
What is obvious
DluTwBootstrap module mimicks the original Zend Framework view helpers where possible. If there is the formRow() view helper in ZF2, DluTwBootstrap has formRowTwb(). Just add Twb suffix.
What is not so obvious
There are two DluTwBootstrap view helpers you should know about which do not have a ZF2 counter part: formFieldsetTwb() which we’ve already talked about (outputs whole fieldsets) and formActionsTwb(). The formActionsTwb() view helper outputs form buttons with correct Twitter Bootstrap mark-up around. See the on-line demo for details.
DluTwBootstrap can optionally highlight required fields. This is something you won’t find in Twitter Bootstrap itself, but I think it’s useful to indicate to the user which fields are mandatory. (I do not want to start a philosophical debate on this, although your opinion is welcome. This feature is optional, so if you think form fields should be never visually marked as required, just ignore it.)
If you want to visually mark a field as required, use the $displayOptions array parameter and set 'required' => true. (See the on-line demo for details.) There are three places where you can specify the element as ‘required’. Their meaning differs though:
- ‘required’ attribute of the element object – just adds the HTML5 ‘required’ attribute to the tag. Makes the form/element semantically correct.
- ‘required’ option of the input filter – forces the user to actually fill out the field otherwise the form won’t validate
- ‘required’ option of the DluTwBootstrap display options – visually marks the element as required/mandatory
Supported elements
All basic elements are supported by DluTwBootstrap. The TODO list contains all HTML5 elements (date, color, etc.), captcha, image and collections. If you need any of them on your form now, you can add markup for them manually in your view script.
DluTwBootstrap benefits
There are two important aspects worth noting: DluTwBootstrap does not force you into a specific form output mode. You can select the required level of control as you wish from fully automated output in one line of code to fully controlled output of the individual atomic form parts. You can also combine these two aproaches at will.
The other strong point of DluTwBootstrap is its clean separation of presentation specifics from the form definition. The form definition (i.e. the form object) contains no information used solely to control output of Twitter Bootstrap markup (e.g. a Twitter Bootstrap CSS class). The user controllable Twitter Bootstrap specifics are contained in the $displayOptions parameter optionaly passed to the Twb view helpers. If you decide to abandon Twitter Bootstrap and use another CSS template system, your form objects are perfectly ok, do not contain any Twitter Bootstrap specific artifacts and do not need any refactoring. Your changes would be kept exclusively inside your view scripts.
BC breaks
There are too many BC to mention them individually. The view helpers are renamed and removed, the parameters changed, the form objects should be defined as per ZF2 RC3 API (which is different – e.g. options instead of attributes), etc. Please check the on-line demo, review the demo form output and examine the source. DluTwBootstrap is easy to use and the best way to learn it is by example.
404 not found on this
https://bitbucket.org/dlu/dlutwbootstrap.git
What are you trying to do? When did you encounter this error? Depending on what you are trying to achieve, you may have to remove the ‘.git’ suffix.
sina@SINA-PC:/var/www$ git clone https://bitbucket.org/dlu/dlutwbootstrap.git dlu
Cloning into ‘dlu’…
error: The requested URL returned error: 407 while accessing https://bitbucket.org/dlu/dlutwbootstrap.git/info/refs
fatal: HTTP request failed
Unfortunatelly I cannot replicate your error (a proxy error). The specified git clone command works ok for me. If you cannot clone for whatever reason, you can download a zip archive (go to https://bitbucket.org/dlu/dlutwbootstrap and click ‘Get source’) or if you are using composer in your project add ‘”dlu/dlutwbootstrap”: “dev-master”‘ among required dependencies.
I did not manage to get to the online demo. Clicking on http://apps.zfdaily.com/dlutwbootstrap-demo redirects to http://apps.zfdaily.com/dlutwbootstrap-demo/tw-bootstrap-demo
Please advise.
Forget about my comment. Was to blind to see the top menu…
No problem
Let me know if you encounter any other problems.
ok
i dont know why im getting this error
Strict standards: Declaration of DluTwBootstrap\Form\View\Helper\FormLabelTwb::__invoke() should be compatible with that of Zend\Form\View\Helper\FormLabel::__invoke() in D:\xampp2\htdocs\farsifood\vendor\DluTwBootstrap\src\DluTwBootstrap\Form\View\Helper\FormLabelTwb.php on line 19
i ve checked sources and your __invoke method arguments are exactly diffrent as zend’s
fixed in your latest commits … thanks
Yes, the code conforms to strict standards now.
(Note: Please udpate to the latest ZF2 version, the recent ZF2 commits contained bug which caused that Select elements would not validate.)
so your module works with RC4?
Yes it does. ZF2′s API is much more stable now so there is a good chance that a new release won’t break the module. RC4 is no exception. If you are installing a ZF2 version which is newer than the supported version specified in the module (e.g. in the README.md), just check the demo to see if the forms are rendered correctly. Once we are past the RC phase, I’ll add formal tests.
Hi David,
nice job you are doing with DluTwBootstrap, I really like it.
Just one question regarding the $displayOptions that are passed to the formTwb() view helper. I understand that defining the CSS classes should be the job of the view script. But I wonder if the additional setting of the required flag could be automated somehow. I already have defined that in my input filter for the same class. Would it be possible to read the required settings from the input filter if attached to the form?
Regards,
Ralf
Another little thing. There is an prependText option that works nicely. I wonder if you could add a prependIcon option as well?
Good point. I am not sure about this. If Twitter Bootstrap supports icons as append/prepend, it won’t much trouble to add this feature to DluTwBootstrap. I’ll check this and post here.
Hi Ralf, thanks for the praise, I am glad the module has been useful.
You are in a way answering your own question (which is a very good one, thanks for it!). The CSS classes are related to view and should be managed by a view layer i.e. the view script. Neither the form definition (the form class) nor the input filter should be “polluted” with view artifacts otherwise these components backfire on us the moment we try to switch the currently used view template (Twitter Bootstrap in this case) for something else. The concept of forms in ZF2 promotes the separation of view related attributes by not giving developers any means of doing
echo $form;in a view script (known from ZF1) and instead forcing them to manually output the individual form elements, which is the right moment to supply view related attributes (e.g. the CSS class).Although I fully support this concept I somehow missed the convenience of
echo $form;. So I decided to include this ability with DluTwBootstrap but did not want to spoil the nicely separated responsibilites. The$displayOptionsfield is the result. It enables you to use the one-liner, supply view related attributes and not abuse inappropriate components for this.So, to (finally) answer your question, it is intentionally not possible to read view attributes from either form or input filter. If you already have a number of input filters which contain view configuration and you do not like the idea of refactoring to the
$displayOptionsarray, you might want to implement a simple extractor which would read the view configuration from your input filter and return the$displayOptionsarray.Hi David,
thanks for your reply. I looked through the code to find out which $displayOptions are supported. I found this hierarchy:
- class
- fieldsets
— class
— display_legend
— elements
—– see below
- elements
— class
— required
— inline (radios and multi checkbox only)
— size (select only)
— rows (textarea only)
All these options are real display options and I think the view script is the right place to define them. So there is no duplicate definition problem, except for the required option. That could be read from the input filter. I am thinking of passing the input filter to the form all the time and write a view helper to get the required definitions from this input filter. Seems quite reasonable to me.
Thanks again.
Anyway, did anything change in Twitter Bootstrap in 2.1.0 regarding the forms?
Ralf
I don’t need a view helper. If the input filter is connected to the form it is trivial. I don’t know if any code is accepted here. So don’t blame me, if this looks funny now:
$inputFilter = $this->form->getInputFilter();
$displayOptions = array(
'elements' => array(
'nickname' => array(
'class' => 'span8',
'required' => $inputFilter->get('nickname')->isRequired(),
),
'password' => array(
'class' => 'span8',
'required' => $inputFilter->get('password')->isRequired(),
),
'email' => array(
'class' => 'span8',
'required' => $inputFilter->get('email')->isRequired(),
),
'firstname' => array(
'class' => 'span8',
'required' => $inputFilter->get('firstname')->isRequired(),
),
'lastname' => array(
'class' => 'span8',
'required' => $inputFilter->get('lastname')->isRequired(),
),
),
);
Hi Ralf, your reasoning is correct except that it won’t work (as you expect)
The trouble is the checkbox element (and possibly others). A former DluTwBootstrap version worked exactly like you suggest – it read the ‘required’ flag from the input filter. But consider this: The checkbox element always automatically sets the input filter’s ‘required’ flag to true (please see
Zend\Form\Element\Checkbox::getInputSpecification())! If you use this flag to visually mark the element as required on your form, all your checkboxes will *always* be visually presented as mandatory! Which might confuse the user into thinking, that she is obliged to check the checkbox.The problem is that the semantic meaning of the ‘required’ flag in the input filter differs from the meaning of the mandatory field on a form. The former simply means that the input filter demands a value for the form element in question is present in the received form data (if it’s not, the validator would complain). The ZF2 checkbox element (by default) generates not only the html input for the checkbox, but also an equally named hidden input which contains the value representing the UNchecked state of the checkbox. Therefore the input filter is always getting something under the checkbox’s name (even if the user does not touch the checkbox), hence the ‘required’ flag of the input filter is absolutely appropriate. On the contrary the visually marked mandatory field on a form means something else – the user HAS TO input something here.
This semantic discrepancy is the reason I could not use the input filter’s ‘required’ flag and had to add yet another one, so that there are three (!) different ‘required’ flags now, each controlling something else. Please re-read this post’s paragraph titled “What is not so obvious”, which comments on the third one.
TwB 2.1.0 is my today’s job, so check the repo after the weekend to see any changes.
The DluTwBootstrap for TwB 2.1.0 is out. Check this post.
Great work, but why no Composer support?
Hi and thanks for this question.
If you are asking about DluTwBootstrap’s dependencies (i.e. ZF2), it is assumed that you already have ZF2 installed (otherwise you would not be playing with any ZF2 module, right?).
If you are asking about installation of DluTwBootstrap as a dependency into your app, the installation via Composer IS in fact supported
It is just undocumented (shame on me, I know, the docs are far from perfect). The package is registered as
dlu/dlutwbootstrap. Just add"dlu/dlutwbootstrap": "dev-master",underrequireinto your composer.json. Actually the on-line demo app uses Composer to install DluTwBootstrap, check its composer.json here: https://bitbucket.org/dlu/dlutwbootstrap-demo-app/src. If you use Composer to install the module, DO NOT forget to:'./vendor/dlu',undermodule_pathsinto yourapplication.config.php, otherwise the module manager won’t find the module.publicfolder contents to thepublicfolder of your app.