Zend Framework 2 - Form Element Decorators

后端 未结 4 691
情话喂你
情话喂你 2020-12-13 22:32

I want to force the Zend form into Twitter Bootstrap style. I currently iterate through the form fields and write the form info into my bootstrap div construction.

I

相关标签:
4条回答
  • 2020-12-13 22:49

    I tried Ron's Partial method, the result would like this which not Bootstrap 3 intended.

    <form id="tea" name="tea" method="POST" action="/tea/add">
        ...
        <div class="form-group">
            <label class="control-label">Brand</label>
            <div class="form-control">
                <input type="text" value="" name="brand">
            </div>
        ...
    

    We know, in order to use bootstrap 3 predefined Form style, we need to define style to input element: form-control, rather than its wrapping element.

    My Partial way is as following.

    echo $this->form()->openTag($form);
    foreach ($form as $element) :?>
        <div class="form-group">
            <?php 
                if ($element->getOption('required')) { $req = 'required'; }
                $type = $element->getAttribute('type');
                $name = $element->getAttribute('name'); 
                $label = $element->getLabel();
            ?>
            <?php if ($name == 'id') { ?>
                <div class="hidden"><?php echo $this->formElement($element); ?></div>
            <?php } else if ($name == 'submit') { ?>
                <input class='btn' name='submit' type='submit' value='Add'>
            <?php } else if ($label != '') { ?>
                <label class="control-label"><?php echo $label ?></label>
                <input class='form-control' name='<?php echo $name ?>' type='<?php echo $type ?>'>
            <?php } ?> 
        </div>
    <?php 
    endforeach;
    echo $this->form()->closeTag();
    

    Well, we could get the result.

    <form id="tea" name="tea" method="POST" action="/tea/add">
        ...
        <div class="form-group">
            <label class="control-label">Brand</label>
            <input class="form-control" type="text" name="brand">
        </div>
    ...
    

    How to attach custom styles into zf2 forms has mentioned : to add class attribute to the Form element.

    class TeaForm extends Form
    {
        public function __construct($name = null)
        {
            // we want to ignore the name passed
            parent::__construct('tea');
    
            $this->add(array(
                'name' => 'id',
                'type' => 'Hidden',
            ));
            $this->add(array(
                'name' => 'brand',
                'type' => 'Text',
                'options' => array(
                    'label' => 'Brand',
                ),
                /** **define class attribute** **/
            'attributes' => array(
                'class' => 'form-control',
            ),
            ));
    ....
    

    It looks quite simple, but, the problem is the input element would be wrapped into the label element, which still not what Bootstrap 3 intended.

    <form id="tea" role="form" name="tea" method="POST" action="/tea/add">
        <input type="hidden" value="" name="id">
        <label>
            <span>Name</span>
            <input class="form-control" type="text" value="" name="name">
        </label>
    ...
    

    In my opinion, the Partial method is still one flexible and light choice. Tea Box is one ZF2 practice, you could find all above mentioned code and description from Gibhub

    0 讨论(0)
  • 2020-12-13 22:52

    I'm using partials now. I'm iterating over the attributes, build a few exceptions for eg CSRF and Submit... This works pretty smooth:

    View

    echo $this->partial('partial/form-partial', array(
    'form' => $this->form,
    'url' =>  $this->url('whatever', array('action' => 'add')))); ?>
    

    Partial

    <?php
    $form = $this->form;
    $form->setAttribute ( 'action', $this->url () );
    $form->prepare ();
    
    echo $this->form ()->openTag ( $form );
    foreach ( $form as $element ) :
    ?>
        <div
            class="control-group <?php if($this->formElementErrors($element)) echo "error" ?>">
            <label class="control-label"><?php echo $element->getLabel() ?></label>
            <div class="controls">
                    <?php echo $this->formElement ( $element );
                        if ($this->formElementErrors ( $element ))
                    ?>
                <span class="help-inline"><?php echo $this->formElementErrors($element) ?></span>
            </div>
        </div>
    <?php
    endforeach;
    echo $this->form ()->closeTag ( $form );
    ?>
    

    The exceptions are left out for clearity's sake...

    0 讨论(0)
  • 2020-12-13 22:53

    I did it the way @Rufinus mentioned. See this Tutorial on how to create View Helpers in ZF2 http://blog.evan.pro/creating-a-simple-view-helper-in-zend-framework-2

    In my case I simply wanted to wrap form elements with list items so I extended the original ZF2 View Helpers and let them do the rendering of the elements. I Just wrapped what they return:

    View Helper FormCollection.php

    <?php
    // ./src/Application/View/Helper/FormCollection.php
    namespace Application\View\Helper;
    
    use Zend\Form\ElementInterface;
    use Zend\Form\View\Helper\FormCollection as BaseFormCollection;
    
    class FormCollection extends BaseFormCollection {
        public function render(ElementInterface $element) {
            return '<ul>'.parent::render($element).'</ul>';
        }
    }
    

    View Helper FormElement.php

    <?php
    // ./src/Application/View/Helper/FormElement.php
    namespace Application\View\Helper;
    
    use Zend\Form\ElementInterface;
    use Zend\Form\View\Helper\FormElement as BaseFormElement;
    
    class FormElement extends BaseFormElement {
    
        public function render(ElementInterface $element) {
            if ($element->getOption('required')) {
                $req = 'required';
            }
            $type = $element->getAttribute('type');
            $name = $element->getAttribute('name');
            return sprintf('<li class="%s %s %s">%s</li>', $name, $req, $type,  parent::render($element));
        }
    }
    

    while my view looks like this and didn't need to be modified for the changes to take effect.

    <?php 
    $form = $this->form;
    $form->prepare();
    echo $this->form()->openTag($form);
    echo $this->formCollection($form);
    echo $this->form()->closeTag($form);
    

    worked like a charm.

    0 讨论(0)
  • 2020-12-13 22:59

    This will make the code easier.

    http://php.net/manual/en/function.echo.php

    <?php 
    
    $form->prepare();
    echo 
    $this->form()->openTag($form),
    $this->formCollection($form),
    $this->form()->closeTag($form);
    
    0 讨论(0)
提交回复
热议问题