zend-frameworkzend-formzend-framework3zend-view

how to show a form in a grid view


I'm trying a bit around with grid views. I show different contents so the user can have something like a dashboard.

Please have a look at the screenshot:

enter image description here

The notizen area should be a search form.

Here part of my controller action:

 $view = new ViewModel();

    $wiedervorlageView = new ViewModel(['wvs' => $this->wvTable->fetchAll()]);
    $wiedervorlageView->setTemplate('layout/template/wiedervorlage');

    $notizenView = new ViewModel(['notizen' => $this->notizenTable->fetchAll()]);
    $notizenView->setTemplate('layout/template/notizen');

    $geburtstageview = new ViewModel();
    $geburtstageview->setTemplate('layout/template/geburtstageview');

    $sidebarBlockView = new ViewModel(['aps' => $this->ansprechpartnerTable->getGeburtstage()]);
    $sidebarBlockView->setTemplate('layout/template/block');

    $geburtstageview->addChild($sidebarBlockView, 'block');

    $view->addChild($wiedervorlageView, 'wiedervorlage')
    ->addChild($notizenView, 'notizen')
    ->addChild($geburtstageview, 'geburtstage');

    return $view;

And here the search viewscript:

<?php
$title = 'Suche';      
$this->headTitle($title);
?>
<h1><?= $this->escapeHtml($title) ?></h1>
<?php

$suche= $form->get('suche');
$suche->setAttribute('class', 'form-control');
$suche->setAttribute('placeholder', 'suche');

$suchtyp= $form->get('suchtyp');
$suchtyp->setAttribute('class', 'form-control');
$suchtyp->setAttribute('placeholder', 'suchtyp');


$submit = $form->get('submit');
$submit->setAttribute('class', 'btn btn-primary');

$form->prepare();

echo $this->form()->openTag($form);
?>

<div class="form-group">
    <?= $this->formLabel($suche) ?>
    <?= $this->formElement($suche) ?>
    <?= $this->formElementErrors()->render($suche, ['class' => 'help-block']) ?>
</div>

<div class="form-group">
    <?= $this->formLabel($suchtyp) ?>
    <?= $this->formElement($suchtyp) ?>
    <?= $this->formElementErrors()->render($suchtyp, ['class' => 'help-block']) ?>
</div>

<?php
echo $this->formSubmit($submit);
echo $this->form()->closeTag();

My question is how to change the notizen area so that it works with the form? I tried different possibilities but I came to the conclusion that I didn't understood the logic in this case. Any help or explanation appreciated.

Solution:

ok I changed to partials, before I wanted to try with the described concept to see the difference to the partials. I worked before with partials,my challenge here was really only the form, now it is clear hopefully. But either way, the concept with the partials is much more convenient and readable.

So, I changed the viewscripts like suggested, here for completion the one with the form:

<div class="row">
<h2> Suche </h2>
<?php
    $suche= $form->get('suche');
    $suche->setAttribute('class', 'form-control');
    $suche->setAttribute('placeholder', 'suche');

    $suchtyp= $form->get('suchtyp');
    $suchtyp->setAttribute('class', 'form-control');
    $suchtyp->setAttribute('placeholder', 'suchtyp');

    $submit = $form->get('submit');
    $submit->setAttribute('class', 'btn btn-primary');

    $form->prepare();

    echo $this->form()->openTag($form);
    ?>

   <div class="form-group">
        <?= $this->formRow($suche) ?>
        <?= $this->formElementErrors()->render($suche, ['class' => 'help-block']) ?>
        <?= $this->formRow($suchtyp) ?>
        <?= $this->formElementErrors()->render($suchtyp, ['class' => 'help-block']) ?>  

        <?php
        echo $this->formSubmit($submit);
        echo $this->form()->closeTag(); ?>

   </div>
</div>

As I posted this I thought I would need to redirect to the controller Action with the search script. Now I copied it to the same controller action. So it works and it is ok for me. Here part of the changed controller action for anybody who has the same understanding issue:

  $form = new SearchForm(NULL);
        $form->get('submit')->setValue('suche');

        return new ViewModel([
            'wvs' => $this->wvTable->fetchAll(),
            'form' => $form,
            'aps' => $this->ansprechpartnerTable->getGeburtstage()
        ]);

Solution

  • You should really learn to create partials. What you're doing now is mixing concerns.

    What you're doing in your controller will give you a giant mess if/when you have to refactor.

    With partials you would do something like this.

    File: notizen-partial.phtml

    <?php
    /** @var array $notizen */
    ?>
    
    <table>
        <tr>
            <th>datum</th>
            <th>text</th>
        </tr>
        <tr>
            <td><?= $notizen['datum'] ?></td>
            <td><?= $notizen['text'] ?></td>
        </tr>
    </table>
    

    So, the above expects a variable $notizen, of type array (hinted in the PHP at the top). You could add some validation that the array is actually present, contains the values, etc. but that's up to you.

    Now, register this partial in the configuration of the module, with the following config:

    'view_manager'    => [
        'template_map'        => [
            'partial/notizen-partial' => __DIR__ . '/../view/partials/notizen-partial.phtml',
        ],
    ],
    

    Make sure you correct the path for your situation!!!

    Repeat the above for each little "container" of your data handling (wvs, aps, etc.).


    Next, have an Action return the data you need to the View:

    // ... create/get data
    
    return [
        'wvs'     => $this->wvTable->fetchAll(),
        'notizen' => $this->notizenTable->fetchAll(),
        'aps'     => $this->ansprechpartnerTable->getGeburtstage(),
    ];
    

    This goes to "action-view.phtml", or whatever. This file handles the "place data where it needs to be".

    The layout of the view, based on your screenshot, would be something like this (I'm going under the assumption your using Bootstrap 4.*):

    <div class="row">
        <div class="col-12">
            <!-- That top row - full width -->
            <!-- ## notizen here ## -->
        </div>
    </div>
    
    <div class="row">
        <div class="col-8">
             <!-- second row - two thirds of width -->
             <!-- Wiedervorlagen here -->
        </div>
        <div class="col-4">
             <!-- second row, second column - one thirds of width -->
             <!-- Geburtstage here -->
        </div>
    </div>
    

    Now, you need to use the additional partials to display the data in the right locations. For example, your 'notizen' data, is now $notizen variable in this view. However, we're not using it in this view, so lets pass it on to the partial we created earlier, like so:

    <?= $this->partial('partial/notizen-partial, ['notizen' => $notizen]) ?>
    

    A lot happening here:

    Place this call in your action view, like so:

    <div class="row">
        <div class="col-12">
            <!-- That top row - full width -->
            <?= $this->partial('partial/notizen-partial, ['notizen' => $notizen]) ?>
        </div>
    </div>
    

    And you're done.


    You now have:


    I've studiously ignored your pasted Form. The principle for that is the same, you could pass the $form in to a partial and have that partial contain the displaying of the form. Creating something re-usable.

    If you'd like to know more about customizing Form ViewHelpers (e.g. FormRow, FormElement, FormNumber, etc.), please see answers I've given others, such as this one.