How to 'validate' a Symfony form in steps - instead of calling $form->isValid()

后端 未结 2 604
野性不改
野性不改 2021-02-04 22:07

I am using Symfony 1.3.6 on Ubuntu.

I have a form with a lot of fields on it - rather than showing all the fields in one go (which may intimidate the user), I want to br

2条回答
  •  臣服心动
    2021-02-04 22:50

    I would utilize a different method to implement multi part forms in Symfony. Hopefully, the following shell is enough to get you started.

    Step 1: Add a stage widget to your form

    public function configure()
    {
      $this->setWidget('stage', new sfWidgetFormInputHidden(array('default' => 1));
      $this->setValidator('stage', new sfValidatorFormInteger(array('min' => 1, 'max' => $maxStages, 'required' => true));
    }
    

    Step 2: Add some information about the stages to your form

    protected $stages = array(
      1 => array('stage1field1', 'stage1field2',
      2 => array('stage2field1', ... //etc for as many stages you have
    );
    

    Step 3: Add a configure as stage method to your form

    public function configureAsStage($currentStage)
    {
      foreach($this->stages as $stage => $field)
      {
        if ($currentStage > $stage)
        {
          $this->setWidget($stage, new sfWidgetFormInputHidden()); //so these values carry through
        }
        if ($stage > $currentStage)
        {
           unset($this[$stage]); //we don't want this stage here yet
        }
      }
    }
    

    Step 4: Override doBind

    You might need to override bind() directly, I forget.

    public function doBind(array $taintedValues)
    {
      $cleanStage = $this->getValidator('stage')->clean($taintedValues['stage']);
      $this->configureAsStage($cleanStage);
      parent::doBind($taintedValues);
    }
    

    Step 5: Add some auxiliary methods to the form

    public function advanceStage()
    {
      if ($this->isValid())
      {
        $this->values['stage'] += 1;
        $this->taintedValues['stage'] += 1;
        $this->resetFormFields();
      }
    }
    
    public function isLastStage()
    {
      return $this->getValue('stage') == count($this->stages);
    }
    

    Step 6: Call configureAsStage/advanceStage as necessary in your action

    public function executeNew(sfWebRequest $request)
    {
      $form = new MultiStageForm($record);
      $form->configureAsStep(1);
    }
    
    public function executeCreate(sfWebRequest $request)
    {
      $record = new Record();
      $form = new MultiStageForm($record);
      $form->bind($request[$form->getName()]);
      if ($form->isValid())
      {
        if ($form->isLastStage())
        {
          $form->save();
          //redirect or whatever you do here
        }
        $form->advanceStage(); 
      }
      //render form
    }
    

    I made this up completely on the fly. I think it should work, but I haven't tested it so there may be some mistakes!

提交回复
热议问题