提交表单时无法获得额外的表单字段

时间:2014-06-12 07:54:54

标签: post symfony1 symfony-1.4

我自动生成的基本表单类如下:

abstract class BaseGestorForm extends BaseFormDoctrine {
    public function setup() {
        $this->setWidgets(array(
            'persona_fk' => new sfWidgetFormInputHidden(),
            'unitat_fk'  => new sfWidgetFormInputHidden(),
            'baixa'      => new sfWidgetFormDateTime(),
        ));
        $this->setValidators(array(
            'persona_fk' => new sfValidatorChoice(array('choices' => array($this->getObject()->get('persona_fk')), 'empty_value' => $this->getObject()->get('persona_fk'), 'required' => false)),
            'unitat_fk'  => new sfValidatorChoice(array('choices' => array($this->getObject()->get('unitat_fk')), 'empty_value' => $this->getObject()->get('unitat_fk'), 'required' => false)),
            'baixa'      => new sfValidatorDateTime(array('required' => false)),
            ));  
        $this->widgetSchema->setNameFormat('gestor[%s]');
        $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);   
        $this->setupInheritance();
        parent::setup();
    }

    public function getModelName() {
        return 'Gestor';
    }
}    

在表格中我添加了两个额外字段(totes_unitatsunitats_a_gestionar)。第一个字段是下拉列表,用户在其中选择一个或多个选项,并在用户按下按钮时使用jquery将所选选项添加到unitats_a_gestionar下拉列表中。同时,这些选项将从totes_unitats列表中删除。

class GestorForm extends BaseGestorForm {   
    public function configure() {
        unset($this['baixa']);

        $this->widgetSchema['persona_fk'] = new sfWidgetFormChoice(array(
            'choices' => UsuariLdap::getAllUsuaris()
        ));

        $this->widgetSchema['totes_unitats'] = new sfWidgetFormChoice(array(
            'choices' => UnitatTable::findAllUnitatsPerOrdreArray(),
            'multiple' => true
        ));

        $this->widgetSchema['unitats_a_gestionar'] = new sfWidgetFormChoice(array(
            'choices' => array(),
            'multiple' => true
        ));

        $this->widgetSchema->setLabels(array(
            'persona_fk' => 'Gestor',
            'unitat_fk' => 'Unitat',
            'totes_unitats' => 'Totes les unitats',
            'unitats_a_gestionar' => 'Unitats a gestionar'
        ));

        $this->validatorSchema->setOption('allow_extra_fields', true);

        $this->validatorSchema['persona_fk'] = new sfValidatorString(array('required' => true), array('required' => 'Requerit'));
    }   
}    

我发现问题出在actions文件中。首先,我调用呈现表单的executeNouGestor方法。然后当用户按下继续并创建Gestor对象时,它会调用验证表单的executeValidaGestor。最后一个方法调用processFormGestor,无法检索unitats_a_gestionar额外字段。

public function executeNouGestor(sfWebRequest $request) {
    $this->gestorForm = new GestorForm();
}

public function executeValidaGestor(sfWebRequest $request) {
    $this->forward404Unless($request->isMethod(sfRequest::POST));
    $this->gestorForm = new GestorForm();   
    $this->processFormGestor($request, $this->gestorForm);
    $this->setTemplate('nouGestor');
}

protected function processFormGestor(sfWebRequest $request, sfForm $gestorForm) {
    $gestorForm->bind($request->getParameter($gestorForm->getName()), $request->getFiles($gestorForm->getName()));
    if ($gestorForm->isValid()) { 
        var_dump($_POST);
        var_dump($request->getParameterHolder()->getAll());
        ...
    }
}

这两个var_dump向我展示了以下信息:

的var_dump($ _ POST):

array(2) {
  ["gestor"]=>
  array(2) {
    ["persona_fk"]=>
    string(3) "330"
    ["_csrf_token"]=>
    string(32) "91e18aa0570bfc7558d21ebb4b98f512"
  }
  ["Desar"]=>
  string(5) "Desar"
}

的var_dump($请求 - > getParameterHolder() - > GETALL()):

array(4) {
  ["gestor"]=>
  array(2) {
    ["persona_fk"]=>
    string(3) "330"
    ["_csrf_token"]=>
    string(32) "91e18aa0570bfc7558d21ebb4b98f512"
  }
  ["Desar"]=>
  string(5) "Desar"
  ["module"]=>
  string(13) "administracio"
  ["action"]=>
  string(12) "validaGestor"
}

因此,正如您所看到的,在["gestor"]中,没有跟踪totes_unitatsunitats_a_gestionar额外的表单字段。我不知道为什么。我在模板中显示表单字段的方式与往常一样:

<?php echo $gestorForm['persona_fk']->renderLabel(); ?>
<div class="input"><?php echo $gestorForm['persona_fk']->render(); ?></div>
<div class="error-input"><?php echo $gestorForm['persona_fk']->renderError(); ?></div>

<?php echo $gestorForm['totes_unitats']->renderLabel(); ?>
<div class="input multiple"><?php echo $gestorForm['totes_unitats']->render(); ?></div>
<div class="error-input"><?php echo $gestorForm['totes_unitats']->renderError(); ?></div>

<?php echo $gestorForm['unitats_a_gestionar']->renderLabel(); ?>
<div class="input multiple"><?php echo $gestorForm['unitats_a_gestionar']->render(); ?></div>
<div class="error-input"><?php echo $gestorForm['unitats_a_gestionar']->renderError(); ?></div>

我还添加了jquery代码,用于管理在具有多个选择的两个下拉列表中添加或删除的选项:

function afegirTreureUnitats() {
  var boto_afegir = $("#btn-multiple-afegir");
  var boto_treure = $("#btn-multiple-treure");
  boto_afegir.click(function() {
    var selectedItems = $("#gestor_totes_unitats option:selected");
    var output = [];
    $.each(selectedItems, function(key, e)
    {
      output.push('<option value="' + e.value + '">' + e.text + '</option>');

    });
    $("#gestor_unitats_a_gestionar").append(output.join(""));
    ordenaOptionsSelect("gestor_unitats_a_gestionar");
    selectedItems.remove();
  });  
  boto_treure.click(function() {
    var selectedItems = $("#gestor_unitats_a_gestionar option:selected");
    var output = [];
    $.each(selectedItems, function(key, e)
    {
      output.push('<option value="' + e.value + '">' + e.text + '</option>');
    });
    $("#gestor_totes_unitats").append(output.join(""));
    ordenaOptionsSelect("gestor_totes_unitats");
    selectedItems.remove();
  });
}

function ordenaOptionsSelect(idSelect)
{
  var options = $('#' + idSelect + ' option');
  options.sort(function(a, b)
  {
    if (a.text > b.text)
      return 1;
    else if (a.text < b.text)
      return -1;
    else
      return 0;
  });
  $('#' + idSelect).empty().append(options);
}

$(document).ready(function() {
  afegirTreureUnitats();
});

呈现的表单具有以下外观:

https://drive.google.com/file/d/0B0Mz720p9Q_DN1RnYWIyR0pXOTQ/edit?usp=sharing

我也发现了一个奇怪的事实。如果我选择下拉列表中的一个选项,totes_unitatsunitats_a_gestionar它们是通过POST方法发送的,但只有一个(如果我选择多个选项,我只能选择其中一个选项)选择)。

1 个答案:

答案 0 :(得分:1)

当您在表单上使用<select>元素或<input>radio类型的checkbox时,只有当字段包含任何内容时,浏览器才会在表单提交时发送其值选择的选项。

<select>标记中的选项列表不会发送回服务器。只有实际选择的选项的值。

您可以通过两种方式解决问题:

  1. 创建一个JS,它将在发送之前修改您的表单,并将选择您列表中的所有项目。通过这种方式,您的表单将发送值,您将能够在服务器端使用它们。

  2. 其他选项是添加两个隐藏字段,这些字段将保留选项列表并将这些列表与<select>字段一起修改。