简体   繁体   English

使用Zend Framework 2中的FormElement ViewHelper渲染自定义表单元素

[英]Render custom Form Elements using the FormElement ViewHelper in Zend Framework 2

I've created a new form element class for a special, complex purpose (text input field with an add-on button to open a "search wizard" popup). 我已经为一个特殊的,复杂的目的创建了一个新的表单元素类(带有附加按钮的文本输入字段,用于打开“搜索向导”弹出窗口)。

To render this element properly, I've also created a form view helper. 为了正确呈现这个元素,我还创建了一个表单视图助手。 Everything works and is fine so far. 到目前为止,一切正常并且很好。

However, if I try to render the form using the FormCollection view helper, the element is rendered as a basic input element. 但是,如果我尝试使用FormCollection视图助手渲染表单,则该元素将呈现为基本输入元素。 That's because the FormElement view helper, which the FormCollection helper relies on, uses a hard-coded series of if clauses to map the element's type to a specific form view helper. 这是因为FormCollection助手依赖的FormElement视图助手使用硬编码的if子句系列将元素的类型映射到特定的表单视图助手。 It can't map my element's class and thus falls back to FormInput . 它无法映射我的元素的类,因此回FormInput

Ie (taken from Zend/Form/View/Helper/FormElement.php, line 41-49): 即(取自Zend / Form / View / Helper / FormElement.php,第41-49行):

    if ($element instanceof Element\Button) {
        $helper = $renderer->plugin('form_button');
        return $helper($element);
    }

    if ($element instanceof Element\Captcha) {
        $helper = $renderer->plugin('form_captcha');
        return $helper($element);
    }

    ...

    $helper = $renderer->plugin('form_input');
    return $helper($element);

and so on. 等等。

I've got a little stuck here because this architecture doesn't really promote extensibility. 我有点卡在这里,因为这种架构并没有真正提升可扩展性。

The only solution that came to my mind (except rendering the form by hand) is to extend the FormElement view helper class and thus create my own CustomFormElement view helper. 我想到的唯一解决方案(除了手工渲染表单)是扩展FormElement视图助手类,从而创建我自己的CustomFormElement视图助手。 However, because of its complexity, I've put the custom element into an own module. 但是,由于其复杂性,我将自定义元素放入自己的模块中。 So I'd have to write this CustomFormElement helper dynamically to add custom elements from any module. 所以我必须动态编写这个CustomFormElement助手来添加来自任何模块的自定义元素。 I don't think this is a recommended procedure. 我不认为这是推荐的程序。

Is there another solution or is maybe even my complete approach unrecommended? 还有其他解决方案,或者甚至是我的完整方法未经推荐? Thanks in advance! 提前致谢!

I think the simplest way is to extend Zend\\Form\\View\\Helper\\FormElement , handle your field types in your render() method and register your FormElement as default FormElement for your application/module. 我认为最简单的方法是扩展Zend\\Form\\View\\Helper\\FormElement ,在render()方法中处理字段类型,并将FormElement注册为应用程序/模块的默认FormElement。 Assuming that you have your custom TestField that you would like to render: 假设您有要呈现的自定义TestField:

namespace Application\Form\View\Helper; 

use \Zend\Form\ElementInterface;
use \Zend\Form\View\Helper\FormElement
use \Application\Form\Element\TestField;

class MyFormElement extends FormElement
{
    public function render(ElementInterface $element)
    {
        $renderer = $this->getView();
        if (!method_exists($renderer, 'plugin')) {
            // Bail early if renderer is not pluggable
            return '';
        }

        //your custom fields go here...
        if ($element instanceof TestField) {
            $helper = $renderer->plugin('\Application\Form\View\Helper\FormTestField');
            return $helper($element);
        }

        return parent::render($element);
    }
}

And in Application/config/module.config.php: 在Application / config / module.config.php中:

'view_helpers' => array(
    'invokables' => array(
         'form_element' => 'Application\Form\View\Helper\MyFormElement',
    )
)

Get your hands on the FormElement view helper any way you can and addType to overwrite the view helper used. FormElement视图助手,并使用addType覆盖所使用的视图助手。 ie in view, just before you render your form: 即在视图中,就在呈现表单之前:

<?php $this->plugin('FormElement')->addType('text', 'formcustom'); ?> 

This will overwrite the view helper used in the FormRow , FormCollection helpers using your view helper by the key name: 这将使用您的视图助手通过键名覆盖FormRowFormCollection助手中使用的视图助手:

in your config 在你的配置中

'view_helpers' => array(
    'invokables' => array(
        'formcustom' => 'Application\Form\View\Helper\FormCustom',
    )
),

When this question was asked the method may not have been there. 当问到这个问题时,方法可能不存在。 But it is now. 但它现在。

The following is what I've done and feels like the right level of keeping things separate and neat. 以下是我所做的,感觉就像保持事物分离和整洁的正确程度一样。

Given: 鉴于:

  • A new element: MyModule\\Form\\MyElement which extends Zend\\Form\\Element 一个新元素:MyModule \\ Form \\ MyElement,它扩展了Zend \\ Form \\ Element
  • A new view helper class for MyElement: MyModule\\Form\\View\\Helper\\FormMyElement which extends Zend\\Form\\View\\Helper\\AbstractHelper MyElement的新视图助手类:MyModule \\ Form \\ View \\ Helper \\ FormMyElement,它扩展了Zend \\ Form \\ View \\ Helper \\ AbstractHelper

Here's how you register your view helper to be used to render your element by adding the following to module.config.php: 以下是通过将以下内容添加到module.config.php来注册用于呈现元素的视图助手的方法:

'view_helpers' => array(
    'invokables'=> array(
        'formMyElement' => 'MyModule\Form\View\Helper\FormMyElement',
    ),
    'factories' => array(
        'formElement' => function($sm) {
            $helper = new \Zend\Form\View\Helper\FormElement();
            $helper->addClass('MyModule\Form\MyElement', 'formMyElement');
            return $helper;
        }
    ),
),

The key is that you are providing a new factory method for FormElement that still creates the same, standard class (no need to override it), but also calls the addClass method to register your custom helper as the proper helper for your custom element. 关键是您为FormElement提供了一个新的工厂方法,它仍然创建相同的标准类(不需要覆盖它),但也调用addClass方法将自定义帮助器注册为自定义元素的正确帮助器。 If you don't want to make the short-name for your helper, you can drop the invokables section and put the FQCN in the addClass call, but I like having the short name available. 如果您不想为助手创建短名称,可以删除invokables部分并将FQCN放入addClass调用中,但我喜欢使用短名称。

This is the best method I've found so far. 这是迄今为止我发现的最佳方法。 Ideally, you wouldn't have to take over the construction of the FormElement and could just modify a config that gets passed to it. 理想情况下,您不必接管FormElement的构造,只需修改传递给它的配置即可。 The downside of this approach is that if you have multiple modules that define custom form elements they are going to clash if they all try to re-define the FormElement factory. 这种方法的缺点是,如果你有多个定义自定义表单元素的模块,如果它们都试图重新定义FormElement工厂,它们将发生冲突。 You can't specify additions in multiple modules this way. 您不能以这种方式在多个模块中指定添加项。 So, if someone finds a better config that can be set that simply gets passed to the FormElement::addClass() method, please let me know. 因此,如果有人发现可以设置的更好的配置,只是简单地传递给FormElement :: addClass()方法,请告诉我。

BTW, I found this page which doesn't address the view helper side of the equation, but talks about registering new form element classes and how to over-ride the built in classes: http://framework.zend.com/manual/current/en/modules/zend.form.advanced-use-of-forms.html 顺便说一句,我发现这个页面没有解决方程式中的视图助手方面,但是讨论了注册新的表单元素类以及如何覆盖内置类: http//framework.zend.com/manual/电流/ EN /模块/ zend.form.advanced -使用-的-forms.html

----custom form element----- ----自定义表单元素-----

namespace App\Form\View\Helper;

use Zend\Form\View\Helper\FormElement as ZendFormElement;

/**
 * Description of FormElement
 */
class FormElement
        extends ZendFormElement
{

    public function addTypes(array $types)
    {
        foreach ($types as $type => $plugin) {
            $this->addType($type, $plugin);
        }
    }

}

---- application module.config.php-------------- ---- application module.config.php --------------

//..........
    'view_helpers' => array(
        'invokables' => array(
            'formRTE' => 'App\Form\View\Helper\FormRTE',
        ),
        'factories' => array(
            'formElement' => function($sm) {
                $helper = new App\Form\View\Helper\FormElement();
                $helper->addTypes(array(
                    'rte' => 'formRTE',
                    ));
                return $helper;
            }
        ),
    ),
//.........

Seems like we're both running into Form issues with Zend. 好像我们都遇到了Zend的Form问题。 I think that it could be better integrated with the whole MVC structure. 我认为它可以更好地与整个MVC结构集成。

I think that your approach is sound. 我认为你的方法很合理。 What I might think of doing is the following 我可能想到的是以下内容

  1. Give your elements a variable named helper like in ZF1. 为您的元素提供一个名为helper的变量,就像在ZF1中一样。
  2. Create the custom form element renderer that will ALSO check the renderer attribute of a form element to decide on how to render it. 创建自定义表单元素渲染器,该渲染器还将检查表单元素的渲染器属性以决定如何渲染它。

You could re-use the ViewHelperProviderInterface or create your own interface: 您可以重新使用ViewHelperProviderInterface或创建自己的界面:

class CustomElement implements ViewHelperProviderInterface
{
     public function getViewHelperConfig()
     {
          return array('type' => '\My\View\Helper');
     }
}

or 要么

class CustomElement implements FormHelperProviderInterface
{
     public function getFormHelperConfig()
     {
          return '\My\View\Helper';
          // or
          return new My\View\Helper();
     }
}

Then in your FormElement class you can do the following: 然后在FormElement类中,您可以执行以下操作:

    if ('week' == $type) {
        $helper = $renderer->plugin('form_week');
        return $helper($element);
    }

    if ($element instanceof THEINTERFACE) {
          return $renderer->plugin($element->getFormHelperConfig());
    }

    $helper = $renderer->plugin('form_input');
    return $helper($element);

This is probably what you had in mind anyway. 这可能是你想到的。

You'd probably be better off creating your own interface since the first one already has some sort of meaning behind it and it might confuse someone. 你可能最好创建自己的界面,因为第一个界面已经有了某种意义,它可能会使某些人感到困惑。

Aside from that, each module would then ONLY have to provide a helper_map key in the module configuration to have it's view helpers available during rendering with the MVC components. 除此之外,每个模块只需要在模块配置中提供一个helper_map键,以便在使用MVC组件进行渲染时可以使用它的视图助手。

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

相关问题 Zend Framework 2自定义ViewHelper,用于控制器中的特定操作 - Zend Framework 2 Custom ViewHelper for specific action in a controller ZF:Zend_Form_SubForm仅使用FormElements和ViewHelper在视图中单独显示元素吗? - ZF: Zend_Form_SubForm display elements in the View on one's own using only FormElements and ViewHelper? 渲染一个Zend_View_Helper_FormElement而不使其成为Zend_Form的一部分 - render a Zend_View_Helper_FormElement without making it part of a Zend_Form Zend Framework / Form Elements:创建自定义类还是? - Zend Framework/Form Elements: Create custom class or? Zend Framework / Form:错误时未显示自定义元素 - Zend Framework/Form: custom elements not shown on error 如何向Zend \\ Form \\ View \\ Helper \\ FormElement的typemap添加自定义Form元素助手? - How do I add a custom Form element helper to Zend\Form\View\Helper\FormElement's typemap? 如何在Zend Framework 1.12中呈现表单元素数组? - How do I render an array of form elements in Zend Framework 1.12? 使用Zend表单在Zend Framework 2中添加自定义属性 - Adding custom attributes in Zend Framework 2 using the Zend Form Zend 框架 - Static 表单元素 - Zend Framework - Static form elements Zend Framework如何使用partialLoop列出表单元素 - Zend Framework How to list form elements using partialLoop
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM