简体   繁体   English

Zend Framework 2 - 表单元素装饰器

[英]Zend Framework 2 - Form Element Decorators

I want to force the Zend form into Twitter Bootstrap style. 我想强制Zend表单进入Twitter Bootstrap风格。 I currently iterate through the form fields and write the form info into my bootstrap div construction. 我目前遍历表单字段并将表单信息写入我的bootstrap div结构。

I saw in Zend Framework 1(!) that there is a way to do this within a decorator. 我在Zend Framework 1(!)中看到有一种方法可以在装饰器中执行此操作。 But for some reason the doc for version 2 doesn't cover this point... 但出于某种原因,版本2的文档并没有涵盖这一点......

I'd like to do something like this: 我想做这样的事情:

protected $_format = '<label for="%s">%s</label>'
             . '<input id="%s" name="%s" type="text" value="%s"/>';

public function render($content)
{
    $element = $this->getElement();
    $name    = htmlentities($element->getFullyQualifiedName());
    $label   = htmlentities($element->getLabel());
    $id      = htmlentities($element->getId());
    $value   = htmlentities($element->getValue());

    $markup  = sprintf($this->_format, $name, $label, $id, $name, $value);
    return $markup;
}

Any ideas? 有任何想法吗?

I'm using partials now. 我现在正在使用partials I'm iterating over the attributes, build a few exceptions for eg CSRF and Submit ... This works pretty smooth: 我正在迭代属性,为例如CSRFSubmit ...构建一些例外...这非常顺利:

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... 为了清楚起见,省略了例外情况......

I did it the way @Rufinus mentioned. 我是按照@Rufinus提到的那样做的。 See this Tutorial on how to create View Helpers in ZF2 http://blog.evan.pro/creating-a-simple-view-helper-in-zend-framework-2 请参阅本教程,了解如何在ZF2中创建View Helpers 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. 在我的情况下,我只是想用表单项包装表单元素,所以我扩展了原始的ZF2 View Helpers并让它们进行元素的渲染。 I Just wrapped what they return: 我刚刚把它们归还了:

View Helper FormCollection.php 查看助手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 查看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. 像魅力一样工作。

I tried Ron's Partial method, the result would like this which not Bootstrap 3 intended. 我尝试了Ron的Partial方法,结果就是这个不是Bootstrap 3的意图。

<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. 我们知道,为了使用bootstrap 3预定义的Form样式,我们需要定义样式到输入元素:form-control,而不是它的包装元素。

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. 如何将自定义样式附加到zf2表单中已提到:将类属性添加到Form元素。

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. 它看起来很简单,但是,问题是输入元素将被包装到label元素中,这仍然不是Bootstrap 3的意图。

<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. 在我看来,Partial方法仍然是一个灵活而轻松的选择。 Tea Box is one ZF2 practice, you could find all above mentioned code and description from Gibhub Tea Box是一个ZF2练习,你可以从Gibhub找到所有上面提到的代码和描述

This will make the code easier. 这将使代码更容易。

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

<?php 

$form->prepare();
echo 
$this->form()->openTag($form),
$this->formCollection($form),
$this->form()->closeTag($form);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM