1

Hi there:) i've got a problem with decorators and form which would be in table and in this table want to have also data from database... I dont have any idea how to do this to have a structure like something below, lets say

<table>
<tr>
  <td><?php echo array[0]['name']?>
//and here input from zend form
  <td>
  <select name='foo' id='bar'>
    <option value='something'>Foo</option>
    <option value='something2'>Foo2</option>
  </select>
  </td>
</tr>
</table>

Ofcourse tr will be more and generated with foreach or some loop.

I have something like this:

<?php

class EditArticles_Form_EditArticles extends Zend_Form
{
protected $uid;

public function render()
{


    /* Form Elements & Other Definitions Here ... */
    $this->setName('editarticles');

    $data = new EditArticles_Model_DbTable_EditArticlesModel();
    $datadata = $data->GetArticlesToEdit($this->getUid());    //here is my data from db


    for ($i=0;$i<count($datadata);$i++)
    {           
        $do = new Zend_Form_Element_Select(''.$i);
        $do->addMultiOption('0', 'Aktywny');
                $do->addMultiOption('1', 'Nieaktywny');

        $this->addElements(array($do));
    }



    $submit = new Zend_Form_Element_Submit('updateart');
    $this->addElement($submit);


    //and here are decorators for array, and i would like to have in this table also data from array containing data from database
    $this->addDecorators(array(

                        'FormElements',
                        array('HtmlTag', array('tag' => 'table', 'id' => 'aaaa', 'style' => 'width:500px;')), 'Form', 

                        ));                 

    $this->setElementDecorators(array(

                        'ViewHelper',
                        array(  array('data' => 'HtmlTag'), array('tag' => 'td', 'style' => 'width:200px;')), 
                                array('Label', array('tag' => 'td')),

                        array(array('row' => 'HtmlTag'), array('tag' => 'tr'))

                        ), 
                        //wykluczenie submita z overrida stulu
                        array('submit'), false);


    return  parent::render();

}


//setting user id for get content from db
public function setUid($uid) {
    $this->uid = $uid;
    return $this;
}

public function getUid() {
    return $this->uid;
}

}
?>

output of code above is something like this: (in red marked where i would like to have that selects from form. In this image the table with data is an other table generated in phtml, but i would like to generate that table by form od just insert only the form elements to that table generated in phtml view).

http://img14.imageshack.us/img14/9973/clipboard01pw.png

Something found here: Zend_Form: Database records in HTML table with checkboxes

but i dont know how to start with that...

Community
  • 1
  • 1
DarAss
  • 97
  • 8

1 Answers1

2

Several comments:

  1. Typically, adding elements to the form is done in init(), rather than render().

  2. If a consumer object (this is this case, the form) needs a dependency (in this case, the article model) to do its work, it is often helpful to explicitly provide the dependency to the consumer, either in the consumer's constructor or via setter method (ex: $form->setArticleModel($model)). This makes it easier to mock the model when testing the form and clearly illustrates the form's dependence on the model.

  3. Re: rendering other content in the form via decorators: Maybe, take a look at the AnyMarkup decorator. It looks like (sorry, can't fully understand the Polish) you want a select box on each row you output. So, you get your rows using the model, loop through the rows, creating your select box on each row. When you assign decorators to the select element - ViewHelper, Errors, probably an HtmlTag decorator to wrap it in a <td> - you also add the AnyMarkup decorator to prepend the a bunch of <td>'s containing your row data, finally wrapping the whole row in <tr>.

Perhaps something like this (not fully tested, just to give the idea):

class EditArticles_Form_EditArticles extends Zend_Form
{
    protected $model;

    public function __construct($model)
    {
        $this->model = $model;
        parent::__construct();
    }

    public function init()
    {
        $rows = $this->model->GetArticlesToEdit($this->getUid());
        $numRows = count($rows);
        for ($i = 0; $i < $numRows; $i++) {
            $do = new Zend_Form_Element_Select('myselect' . $i);
            $do->addMultiOption('0', 'Aktywny');
            $do->addMultiOption('1', 'Nieaktywny');
            $do->setDecorators(array(
                'ViewHelper',
                array(array('cell' => 'HtmlTag'), array(
                        'tag' => 'td'
                )),
                array('AnyMarkup', array(
                        'markup' => $this->_getMarkupForRow($i, $row),
                        'placement' => 'PREPEND',
                )),
                array(array('row' => 'HtmlTag'), array(
                        'tag' => 'tr'
                )),
            ));
            $this->addElement($do);
        }
    }

    protected function _getMarkupForRow($i, $row)
    {
        return '<td>' . $i . '</td>' .
            '<td>' . $row['nazwa'] . '</td>' .
            '<td>' . $row['typ'] . '</td>' .
            '<td>' . $row['rozmiar'] . '</td>';
    }
}

A final note: Remember to register an element decorator prefix path as follows (in the form, probably in init()):

$this->addElementPrefixPath('My_Decorator', 'My/Decorator', self::DECORATOR);

This allows the element to resolve the short name AnyMarkup into a full classname My_Decorator_AnyMarkup.

David Weinraub
  • 14,144
  • 4
  • 42
  • 64
  • render() was used because in init() $this->uid was not passed properly and here on stackoverflow i read that i can use render for that:) ill try your answer today:) – DarAss Nov 22 '11 at 13:28
  • If the `$uid` needs to get passed in from the outside, then I guess it could also be part of the constructor (`public function __construct($uid, $model){}`) or set using your `setUid($uid)` method. If it's necessary, then constructor injection is probably best. – David Weinraub Nov 22 '11 at 14:21
  • i don't understand what to do with AnyMarkup... :( i still got: Warning: Exception caught by form: Plugin by name 'AnyMarkup' was not found in the registry – DarAss Nov 22 '11 at 15:18
  • actually is it bad if i do an form and data from db manually in phtml file? Cause i'm trying to do this from 3 days and im already verry frustrated:( – DarAss Nov 22 '11 at 15:20
  • Hey, we all sometimes succumb to the temptation to hack something in. But two ideas before you give up. (1) Register an element decorator prefix to be able to use the AnyMarkup decorator. I'll add details as an update to the answer. Failing that, you could try (2) Use the [ViewScript decorator](bit.ly/tdy2vV) for the form. – David Weinraub Nov 22 '11 at 16:01
  • I created folder Xtra/Decorators in library folder, created file AnyMarkup inside and added code from Davids answer and already registered frefix :) but no results. In config.ini added path and thats why i wrote cause still have that error :) – DarAss Nov 22 '11 at 16:14
  • ok it worked now but only ine problem i have now :) id dont pass td and tr table tahs and outputs everything in one line ;) time for "debugging" :) – DarAss Nov 22 '11 at 16:19
  • `$this->addDecorators(array( 'FormElements', array('HtmlTag', array('tag' => 'table', 'style' => 'width:500px;')), 'Form', ));` works fine :) problem solved – DarAss Nov 22 '11 at 17:16
  • is there a possibility to add static tr and td with description to a top of that table and set submit to be in last td at the bottom? i added submit but it puts it on the left. i would like to have it on right site (` here submit ` ) – DarAss Nov 22 '11 at 17:52
  • You need to be sure that you decorate the submit button with 's and a , as well as decorate the form with a . Without that, the form will render with invalid markup that will display all goofy.
    – David Weinraub Nov 24 '11 at 08:42
  • it is in the same table in td but i'd like to give it on the right side of the table so i have to make 3 blank td's and then in four one submit but i have no idea how to do it:) – DarAss Nov 24 '11 at 16:41