开发者

sfWidgetFormDoctrineChoice for NestedSet model

I'm experiencing a difficulty in rendering sfWidgetFormDoctrineChoice (set of checkboxes) widget for a NestedSet structure.

class ModelForm extends BaseMode开发者_如何学JAVAlForm
{
  public function configure()
  {
      $this->setWidget('relatedmodel_list', new sfWidgetFormDoctrineChoice(array(
        'expanded' => true,
        'multiple' => true,
        'model' => 'Relatedmodel',
        'table_method' => 'fetchTree'
      )));
  }
}
class RelatedmodelTable extends Doctrine_Table
{
  /**
   * Gets tree elements in one query (one root only)
   */
  public function fetchTree()
  {
    $q = $this->createQuery('m')
      ->addOrderBy('m.lft');

    $tree = $q->execute(array(),  Doctrine_Core::HYDRATE_RECORD_HIERARCHY);

    return $tree;
  }
}

Now, if I just render form like this: <?php echo $form['relatedmodel_list'] ?> It will only display form widgets (checkboxes) for first level elements of my hierarchy.

I am looking for an implementation that will allow me to iterate over widget's choices the way I would iterate over collection:

<?php foreach ($form['relatedmodel_list'] as $widget): ?>
  <?php echo $widget->render() ?>
  <?php foreach ($widget->getChildren() as $child_widget): ?>
    <?php echo $child_widget->render() ?>
  <?php endforeach; ?>
<?php endforeach; ?>


I'm using sfWidgetFormTree to display my nestedSet. If you really want to display your tree in a flat way don't use HYDRATE_RECORD_HIERARCHY.

The widget linked is very convinient, you just have to provide a choices array like this :

$choices = array(
    1=> array('label'=>'test', 'children'=>array(
      2=> array('label'=>'test2', 'children'=> array(
        3=> array('label'=>'test3'),
        4=> array('label'=>'hans')
      )),
      5=> array('label'=>'wurst')
    )),
    6=>array('label'=>'letzter')
  );


If anyone cares, I think I found a wonderful solution which allows you to recursively iterate over checkboxes in template. The idea behind it is that you configure 'relatedmodel_list' widget as a single checkbox and render it many times in your template (while iterating over relatedmodel collection).

class ModelForm extends BaseBookForm
{
  public function configure()
  {
    $this->setWidget('relatedmodel_list', new myWidgetFormInputCheckbox());
  }
}

Checkboxes now have incorrect name and value attributes. This can be fixed very easily:

class myWidgetFormInputCheckbox extends sfWidgetFormInputCheckbox
{
  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    //fix value checking
    if (in_array($attributes['value'], (array)$value))
    {
      $attributes['checked'] = 'checked';
    }
    //fix name for multiple
    $name = $name . "[]";

    return parent::render($name, null, $attributes, $errors);
  }
}

Now we can recursively render our form widget in template:

//_form.php
<ul>
  // Model::getRelatedTree() is proxy to Relatedmodel::fetchTree()
  <?php include_partial('node', array('node' => $form->getObject()->getRelatedTree(), 'form' => $form)) ?>
</ul> 

//_node.php
<?php foreach ($node as $item): ?>
<li>
  <?php echo $form['pages_list']->render(array('value'=>$item->id)) ?>
  <?php echo $form['pages_list']->renderLabel((string)$item) ?>
  <?php if (isset($item['__children']) && count($item['__children']) > 0): ?>
  <ul>
    <?php include_partial('node', array('node' => $item['__children'], 'form' => $form)) ?>
  </ul>
  <?php endif; ?>
</li>
<?php endforeach; ?>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜