Use zend-decorator to format Zend_Form_Element_Radio in a table column with oher Zend_Form_Elements in rows

前端 未结 4 943
南笙
南笙 2021-01-20 19:17

I want use decorators to format as table the following Zend_Form, placing a description in the first column and the Zend_Form_Element_Radio\'s opti

相关标签:
4条回答
  • 2021-01-20 19:56

    you do not can to do what you want accomplish with a view helper, in my view!

    you should make a custom form printing, such as:

    <form action="/" method="POST">
        <table>
            <thead>
            <tr>
                <th></th>
                <th>kind</th>
                <th>drink</th>
                <th>food</th>
            </tr>
            </thead>
            <tbody>
                <?for ($i = 1; $i <= 6; $i++) : ?>
                    <?
                    $drink = 'drink_' . $i;
                    $food = 'food_' . $i;
                    ?>
                    <tr>
                        <td>Description row <?=$i?></td>
                        <td>
                            <?=$this->form->$drink?>
                        </td>
                        <td>
                            <?=$this->form->$food?>
                        </td>
                    </tr>
                <? endfor;?>
            </tbody>
        </table>
    </form>
    

    lunch for the field, it is impossible to use it as you ask, you should think of another strategy. At the moment I can think of!

    0 讨论(0)
  • 2021-01-20 20:03

    Well here my version of the answer.

    Into the init I've add a custom decorator RadioTable to the form, and prefix path to load the decorator

    then I decorate all the elements as a normal table, this's important because all my efforts are to keep the facilities offer by standard decorators like "Error"

    Please note the Custom_Form_Element_FirstSelect and the ->setSeparator in the radio element

    I also add the submit button

    public function init()
    {
        $_please_select = array("" => " please select ");
    
        // I add a my custom decorator
        $this->addPrefixPath('Custom_Form_Decorator',
                                 'Custom/Form/Decorator',
                                 'decorator');
    
        $this->setMethod(Zend_Form::METHOD_POST);
    
        $input_lunch = new Zend_Form_Element_Radio('lunch');  
        $input_lunch ->setMultiOptions(self::$KINDS)
                     ->setSeparator("\t__RADIO_SEPARATOR__\t")  //set custom separator I'll use in custom decorator
                     ->setDecorators(array(
                         'ViewHelper',  // add a standard decorator
                         'Label', // I'll use the label decorator to show text
                       ));
    
        $this->addElement($input_lunch );
    
        foreach (self::$KINDS as $k => $_description) {
            // to "mark" the first select I extend the Zend_Form_Element_Select
            // with Custom_Form_Element_FirstSelect
            $input_drink = new Custom_Form_Element_FirstSelect('drink_' . $k);
            $input_drink->addMultiOptions(self::$DRINKS)                    
                        ->setDecorators(array(
                                        'ViewHelper', // add a standard decorator
                                        array(array('data' => 'HtmlTag'),array('tag' => 'td')), // add a standard decorator
                                            ));
    
            $input_food = new Zend_Form_Element_Select('food_' . $k);
            $input_food->addMultiOptions($_please_select)
                ->addMultiOptions(self::$FOODS)
                ->setDecorators(array(
                                'ViewHelper',
                                array(array('data' => 'HtmlTag'),array('tag' => 'td')),
                                ));
    
            $this->addElement($input_drink);
            $this->addElement($input_food);
        }
    
        // add a the submit button
        $submit = new Zend_Form_Element_Submit('submit');
            $submit->setLabel('SUBMIT');
            $submit->setDecorators(array(
                                    'ViewHelper',
                                    'Errors',
                                    array(array('data' => 'HtmlTag'), array('tag' => 'td', )),
                                    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
                                ));
            $this->addElement($submit);
    
        // add the custom decorators to the whole form
        $this->setDecorators(array(
            'RadioTable',
            array('HtmlTag', array('tag' => 'table', )),
            'Form'
        ));
    }
    

    the Custom_Form_Element_FirstSelect

    class Custom_Form_Element_FirstSelect extends Zend_Form_Element_Select{
    
    }
    

    the Custom_Form_Decorator_RadioTable

    class Custom_Form_Decorator_RadioTable extends Zend_Form_Decorator_Abstract {
    
        public function render($content){
    
            $wrap = '';
            // I'll take the element
            $radioElement  = $this->getElement()->getElement('lunch');
            // then I render it and explode in array using the separator
            $arrayRadio = explode("\t__RADIO_SEPARATOR__\t", $radioElement->__toString());
    
    
    
            $count = 0;
            $arrayElement  = $this->getElement()->getElements(); 
            // loop on all form elements and I render them
            foreach ($arrayElement as $keyForm => $element){
                // I skip the radio element 
                if($element instanceof Zend_Form_Element_Radio){
                    continue;
                }
    
                if($element instanceof Custom_Form_Element_FirstSelect ){
                    // when I found the custom select element I'll prefix with "open-row-tag" and radio button in column
                    $wrap .= "<tr>". "<td>". $arrayRadio[$count++] . "</td>" .  $element->__toString();
                    // note that the select elements are already decorated
                } else if($element instanceof Zend_Form_Element_Select){
                    // after the last select I close the row
                    $wrap .= $element->__toString() ."</tr>";
    
                }
    
                if($element instanceof Zend_Form_Element_Submit){
                    // add the SUBMIT button
                    $wrap .=  $element->__toString() ;
    
                }
            }
    
            return $content.$wrap;
        }
    }
    

    Of course I can use the name of the element instead of use a custom element class to open the table row, but in this way I'm feel more flexible.

    0 讨论(0)
  • 2021-01-20 20:12

    I would suggest a solution based on this answer here https://stackoverflow.com/a/8451723/212940

    Your form:-

    class My_Form extends Zend_Form
    {
        const KIND_1 = 'dineer1';
        const KIND_2 = 'dineer2';
        const KIND_3 = 'dineer3';
        const KIND_4 = 'dineer4';
        const KIND_5 = 'dineer5';
        const KIND_6 = 'dineer6';
    
        public static $KINDS = array(
            1 => self::KIND_1,
            2 => self::KIND_2,
            3 => self::KIND_3,
            4 => self::KIND_4,
            5 => self::KIND_5,
            6 => self::KIND_6,
        );
    
        const DRINK_C = 'c';
        const DRINK_M = 'm';
        const DRINK_W = 'w';
    
        public static $DRINKS = array(
            self::DRINK_C => "cole",
            self::DRINK_M => "milk",
            self::DRINK_W => "water",
        );
    
        const FOOD_B = 'b';
        const FOOD_F = 'f';
        const FOOD_M = 'm';
        const FOOD_P = 'p';
        const FOOD_V = 'v';
        const FOOD_W = 'w';
    
        public static $FOODS = array(
            self::FOOD_B => "burger",
            self::FOOD_F => "fruit",
            self::FOOD_M => "Meat",
            self::FOOD_P => "pizza",
            self::FOOD_V => "vegetables",
            self::FOOD_W => "Wursterl",
        );
    
        public function init()
        {
            $this->addDecorators(
                array(
                    array('ViewScript', array('viewScript' => 'forms/_form_test.phtml'))
                )
            ); //added as part of answer. Note all default decorators are still available.
    
            $_please_select = array("" => " please select ");
    
            $this->setMethod(Zend_Form::METHOD_POST);
    
            $input_lunch = new Zend_Form_Element_Radio('lunch');  
            $input_lunch ->setMultiOptions(self::$KINDS) ;
            $this->addElement($input_lunch );
    
            foreach (self::$KINDS as $k => $_descriprion) {
                $input_drink = new Zend_Form_Element_Select('drink_' . $k);
                $input_drink->addMultiOptions(self::$DRINKS);
    
                $input_food = new Zend_Form_Element_Select('food_' . $k);
                $input_food->addMultiOptions($_please_select)
                    ->addMultiOptions(self::$FOODS);
    
                $this->addElement($input_drink);
                $this->addElement($input_food);
            }
            $this->setElementDecorators(array('ViewHelper'));//added as part of answer
        }
    }
    

    As you can see it requires only two small changes.
    Then you need to create the file scripts/forms/_form_test.phtml which contains:-

    <form
        id='contact' 
        action='<?php echo $this->element->getAction(); ?>' 
        method='<?php echo $this->element->getMethod(); ?>'
    >
    <table>
        <thead>
            <tr>
                <th></td>
                <th>kind</td>
                <th>drink</td>
                <th>food</td>
            </tr>
        </thead>
        <tbody>
            <?php 
            $elements = $this->element->getElements();
            $options = $this->element->lunch->getMultiOptions();
            foreach($options as $key => $option){
                echo "<tr>\n";
                echo "<td>Description row $key</td>\n";
                echo "<td><input type='radio' name='lunch' value='$option'</td>\n";
                echo "<td>{$elements['drink_' . $key]}</td>\n";
                echo "<td>{$elements['food_' . $key]}</td>\n";
                echo "</tr>\n";
            }
            ?>
            </tbody>
            <table>
    </form>
    

    The file _form_test.phtml is effectively your decorator for rendering the form. This is a very flexible way of using Zend_Form and I learnt how to do this by reading this article here

    The default decorators, such as 'error' should still be available with this method.

    On my system I got the exact html output you asked for. Try it and see.

    0 讨论(0)
  • 2021-01-20 20:13

    This might not be the prefect solution but it might help you!

    class My_Form extends Zend_Form
    {
        const KIND_1 = 'dineer1';
        const KIND_2 = 'dineer2';
        const KIND_3 = 'dineer3';
        const KIND_4 = 'dineer4';
        const KIND_5 = 'dineer5';
        const KIND_6 = 'dineer6';
    
        public static $KINDS = array(
            1 => self::KIND_1,
            2 => self::KIND_2,
            3 => self::KIND_3,
            4 => self::KIND_4,
            5 => self::KIND_5,
            6 => self::KIND_6,
        );
    
        const DRINK_C = 'c';
        const DRINK_M = 'm';
        const DRINK_W = 'w';
    
        public static $DRINKS = array(
            self::DRINK_C => "cole",
            self::DRINK_M => "milk",
            self::DRINK_W => "water",
        );
    
        const FOOD_B = 'b';
        const FOOD_F = 'f';
        const FOOD_M = 'm';
        const FOOD_P = 'p';
        const FOOD_V = 'v';
        const FOOD_W = 'w';
    
        public static $FOODS = array(
            self::FOOD_B => "burger",
            self::FOOD_F => "fruit",
            self::FOOD_M => "Meat",
            self::FOOD_P => "pizza",
            self::FOOD_V => "vegetables",
            self::FOOD_W => "Wursterl",
        );
    
        public function init()
        {
            $_please_select = array("" => " please select ");
    
            $this->setMethod(Zend_Form::METHOD_POST);
            $this->setDisableLoadDefaultDecorators(true);
    
            $countRows = count(self::$KINDS)+1;
            foreach (self::$KINDS as $k => $_descriprion) {
    
                $rowForm = new Zend_Form_SubForm();
    
                $input_lunch = new Zend_Form_Element_Radio('lunch',
                    array('disableLoadDefaultDecorators' => true, 
                    'label' => 'kind', 
                    'label_placement' => 'prepend'));
                $input_lunch ->setMultiOptions(self::$KINDS) ;
                $input_lunch->addDecorators(array(
                    array('ViewHelper'),
                    array('Label', 
                    array('style' => 'display:block;font-weight:bold', // just for this example
                        'placement'=>'PREPEND',
                        'tag'=>'span', //if you want to use other tag
                        'disableFor'=>true) 
                    ),
                    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'rowspan' => $countRows )),
                ));
                $this->addElement($input_lunch);
    
                // add label just for the first element
                $drinkLabel = array('disableLoadDefaultDecorators' =>true);
                $drinkDecorators = array(
                    array('ViewHelper'),
                    array(array('data' => 'HtmlTag'), array('tag' => 'td')),
                );
                if ($k == 1) {
                    $drinkLabel['label'] = 'drink';
                    $drinkDecorators = array(
                        array('ViewHelper'),
                        array('Label', 
                        array('style' => 'display:block;font-weight:bold',
                            'placement'=>'PREPEND',
                            'tag'=>'span', //if you want to use other tag
                            'disableFor'=>true) 
                        ),
                        array(array('data' => 'HtmlTag'), array('tag' => 'td')),
                    );
                }
    
                $input_drink = new Zend_Form_Element_Select('drink', $drinkLabel);
                $input_drink->addMultiOptions(self::$DRINKS);
                $input_drink->addDecorators($drinkDecorators);
    
                $input_food = new Zend_Form_Element_Select('food', $drinkLabel);
                $input_food->addMultiOptions($_please_select)
                          ->addMultiOptions(self::$FOODS);
                $input_food->addDecorators($drinkDecorators);
    
                $rowForm->addElement($input_drink);
                $rowForm->addElement($input_food);
    
                $rowForm->setSubFormDecorators(array(
                    'FormElements',
                    array('HtmlTag', array('tag' => 'tr')),
                ));
                $rowForm->setDisableLoadDefaultDecorators(true);
    
                $this->addSubForm($rowForm, 'row_' . $k);
            }
    
            $this->setSubFormDecorators(array(
              'FormElements',
              array('HtmlTag', array('tag' => 'tr')),
            ));
    
            $this->setDecorators(array(
                'FormElements',
                array('HtmlTag', array('tag' => 'table')),
                'Form'
            ));
        }
    }
    

    Also, here are some resources to work with table and Zend_Form

    http://www.packtpub.com/article/create-shopping-cart-using-zend-framework-2 http://davidcaylor.com/2008/03/24/building-table-based-forms-in-zend_form/ http://blog.kosev.net/2010/06/tutorial-create-zend-framework-form.html

    0 讨论(0)
提交回复
热议问题