基于 1 对 n 关系的动态添加表单字段 - 有哪些框架替代方案? [英] Dynamic added form fields based on 1-to-n relation - What framework alternatives?

查看:15
本文介绍了基于 1 对 n 关系的动态添加表单字段 - 有哪些框架替代方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们必须开发一个多模型表单,它应该使用 ajax 调用来动态添加或删除子模型字段集.

例如,让我们想象一下这个团队形式场景:

团队:队名:团队国家:成员:会员A姓名:会员A年龄:[添加另一个成员][注册团队和成员]

我们目前正在使用 Yii.据我们所知Yii 不支持开箱即用(也没有任何扩展可以做到这一点).如果你还没有这样做,请不要告诉我有.据我们所知,如果没有大量的扩展工作,目前这是不可能的.

所以,我们可以尝试整合 Zend 表单集合 但它似乎很痛苦.

所以,Zend 确实有这个.

我的问题很简单:

在座的所有开发人员和程序员中,使用 php 框架的,您使用什么框架来完成上述场景?除了 Zend 之外,我们知道,它已经有了.

解决方案

这里是最终的解决方案,表单 id 是 #quoteForm.在这里,您合并"了两个活动表单的设置:

//添加汽车按钮$("#addCar").on('click', function(){$.get('<?php echo Yii::app()->createAbsoluteUrl('quote/addCar'); ?>' + '?index=' + (carCount+1), function(data) {var settings = $("#quoteForm").data('settings');$("#quoteForm").data('settings', null);$("#carlist").append(data);var settings_new = $("#quoteForm").data('settings');车数++;$.each(settings_new.attributes, function(k, v) {settings.attributes.push(v);});//设置新设置$("#quoteForm").data('settings', settings);});

我实际上使用了从 CActiveForm 扩展的 ActiveForm 类,并且有这个方法可以在不运行小部件的情况下将 JS 添加到客户端脚本中(从 CActiveForm->run() 中提取):

公共函数 registerJs(){$options=$this->clientOptions;if(isset($this->clientOptions['validationUrl']) && is_array($this->clientOptions['validationUrl']))$options['validationUrl']=CHtml::normalizeUrl($this->clientOptions['validationUrl']);$options['attributes']=array_values($this->attributes);if($this->summaryID!==null)$options['summaryID']=$this->summaryID;if($this->focus!==null)$options['focus']=$this->focus;if(!empty(CHtml::$errorCss))$options['errorCss']=CHtml::$errorCss;$options=CJavaScript::encode($options);$cs=Yii::app()->clientScript;$cs->registerCoreScript('yiiactiveform');$id=$this->id;$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiactiveform($options);");}

这是控制器部分.您创建了一个表单,但只呈现字段,而不是将其用作小部件:

 $form = new ActiveForm();$form->enableAjaxValidation = false;$form->enableClientValidation = true;$form->id = 'quoteForm';$car = new QuotesHistory();$this->renderPartial('car_row', compact('car', 'carMakes', 'index', 'form'), false, true);

这里是部分视图的一小部分($index 实际上是在 get 请求中传递的 carCount),而且这个部分有更多的字段,它们都验证并正确提交:

<?phpecho $form->hiddenField($car, "[$index]id");echo $form->label($car, "[$index]automake_id", array('class'=>'form-label'));echo $form->dropDownRow($car, "[$index]automake_id", CHtml::listData($carMakes, 'id', 'name'), array('数据目标' =>CHtml::activeId($car, "[$index]automodel_id"),'空'=>'选择制作',));echo $form->error($car, "[$index]automake_id", array('class'='alert-msg','样式'=>'边距:0;'));?>

在最后一部分,您需要在视图的末尾添加它,以便注册 JS.:

request->isAjaxRequest)//我们在正常渲染中不需要这个$form->registerJs();?>

最后一步:为了使所有这些工作正常运行,您不应在 ajax 响应中双重包含任何 JS 库.您可以在 jQuery 中执行此操作 - http://www.eirikhoem.net/blog/2011/08/29/yii-framework-preventing-duplicate-jscss-includes-for-ajax-requests/

我现在已经测试了这段代码,它可以工作.如果我删除元素,则提交表单没有问题.

We have to develop a multi-model form that should use ajax calls to dynamically add or remove, sub-model fieldsets.

For example, let's imagine this team form scenario:

Team:
Team Name: 
Team Country:

Members:
Member A name: 
Member A age: 
      [add another member]

[REGISTER TEAM AND MEMBERS]

We are using Yii at the moment. As as far as we can tell Yii doesn't support this out of the box (nor there is any extension that does this). Please don't tell me that there is, if you have not done it. As far as we can tell, that's not possible at the moment without A LOT of extending work.

So, we may try to integrate Zend Form Collections but it seems a pain.

So, Zend do have this.

My question is quite simple:

From all developers and programmers here present, that use php frameworks, what framework do you use, in order to accomplish the scenario described above? Other than Zend, that, we know, do have this already.

解决方案

Here is the final solution, form id is #quoteForm. Here you "merge" the settings of the two active forms:

//Add car button
        $("#addCar").on('click', function(){
            $.get('<?php echo Yii::app()->createAbsoluteUrl('quote/addCar'); ?>' + '?index=' + (carCount+1), function(data) {
                var settings = $("#quoteForm").data('settings');
                $("#quoteForm").data('settings', null);
                $("#carlist").append(data);
                var settings_new = $("#quoteForm").data('settings');
                carCount++;

                $.each(settings_new.attributes, function(k, v) {
                    settings.attributes.push(v);
                });
               //set the new settings
               $("#quoteForm").data('settings', settings);
        });

I actually use ActiveForm class which extends from CActiveForm and has this method which adds JS to the client script without running the widget(extracted form CActiveForm->run()):

public function registerJs()
{
    $options=$this->clientOptions;
    if(isset($this->clientOptions['validationUrl']) && is_array($this->clientOptions['validationUrl']))
        $options['validationUrl']=CHtml::normalizeUrl($this->clientOptions['validationUrl']);

    $options['attributes']=array_values($this->attributes);

    if($this->summaryID!==null)
        $options['summaryID']=$this->summaryID;

    if($this->focus!==null)
        $options['focus']=$this->focus;

    if(!empty(CHtml::$errorCss))
        $options['errorCss']=CHtml::$errorCss;

    $options=CJavaScript::encode($options);
    $cs=Yii::app()->clientScript;
    $cs->registerCoreScript('yiiactiveform');
    $id=$this->id;
    $cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiactiveform($options);");
}

And here is the controller part. You create a form but only render fields, not using it as a widget:

 $form = new ActiveForm();
 $form->enableAjaxValidation = false;
 $form->enableClientValidation = true;
 $form->id = 'quoteForm';


 $car = new QuotesHistory();
 $this->renderPartial('car_row', compact('car', 'carMakes', 'index', 'form'), false, true);

Here is a small part of the partial view($index is actually the carCount that is passed in the get request), also this partial has a lot more fields and they all validate and submit correctly:

<div class="field-box">
            <?php
                echo $form->hiddenField($car, "[$index]id");
                echo $form->label($car, "[$index]automake_id", array('class'=>'form-label'));

                echo $form->dropDownRow($car, "[$index]automake_id", CHtml::listData($carMakes, 'id', 'name'), array(
                    'data-target' => CHtml::activeId($car, "[$index]automodel_id"),
                    'empty'=>'Select Make',
                ));

                echo $form->error($car, "[$index]automake_id", array(
                    'class'=>'alert-msg',
                    'style'=>'margin: 0;'
                ));
        ?>
    </div>

And on the last partial you need to add this in the end of the view so that the JS is registered.:

<?php
if(Yii::app()->request->isAjaxRequest)  //we dont need this in normal render  
    $form->registerJs();
?>

One final step: In order all this to works you should not double include any JS libs in the ajax response. You can do this in jQuery - http://www.eirikhoem.net/blog/2011/08/29/yii-framework-preventing-duplicate-jscss-includes-for-ajax-requests/

I've tested this code now and it works. If I remove elements I have no problem submitting the form.

这篇关于基于 1 对 n 关系的动态添加表单字段 - 有哪些框架替代方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆