开发者

Is there a way to generate views from Zend_Form ? (read-only)

I was wondering if is there an easy way to generate views from form objects when dealing with CRUDs.

I mean, when we have these开发者_如何学JAVA options: VIEW | EDIT | DELETE I want my VIEW option like EDIT option, but without form elements, just the values.

This will minimize so much the time spent to create these views.

Someone knowks something like that?


In my last project I had this dilemma too. My solution may not be the most elegant, but it did the job. Mind you, I use a Form viewscript decorator in stead of a full decorator generated elements. But you could adjust this example to use decorators I presume. What I'm showing is a very basic example, to give you a general idea. Here's what I did:

class Cms_Form_Page extends Zend_Form
{
  const FOR_CREATE = 'forCreate';
  const FOR_READ   = 'forRead';
  const FOR_UPDATE = 'forUpdate';
  const FOR_DELETE = 'forDelete';

  protected $_name = 'page';

  private $_for;

  private $_viewScripts = array(
    self::FOR_CREATE => 'page-manager/partials/form-page-create.phtml',
    self::FOR_READ => 'page-manager/partials/form-page-read.phtml',
    self::FOR_UPDATE => 'page-manager/partials/form-page-update.phtml',
    self::FOR_DELETE => 'page-manager/partials/form-page-delete.phtml'
  );

  public function __construct( $for = self::FOR_CREATE, $options = null )
  {
    $this->_for = $for;

    parent::__construct( $options );
  }

  public function init()
  {
    $this->setName( $this->_name )
        ->setAttribs( array( 'accept-charset' => 'utf-8' ) )
        ->setDecorators( array(
            'PrepareElements',
            array( 'ViewScript', array( 'viewScript' => $this->_viewScripts[ $this->_for ] ) ),
            'Form'
        ) );

    $elements = array();

    swith( $this->_for )
    {
      case self::FOR_CREATE:
        $title = new Zend_Form_Element_Text( 'title' );
        $elements[] = $title;
        break
      case self::FOR_READ:
        $id = new Zend_Form_Element_Hidden( 'id' );
        $elements[] = $id;
        break;
      case self::FOR_UPDATE:
        $id = new Zend_Form_Element_Hidden( 'id' );
        $elements[] = $id;
        $title = new Zend_Form_Element_Text( 'title' );
        $elements[] = $title;
      break;
        case self::FOR_DELETE:
        $id = new Zend_Form_Element_Hidden( 'id' );
        $elements[] = $id;
        break;
      default:
        throw new Exception( 'invalid Form type' );
    }

    $submit = new Zend_Form_Element_Button( 'submit' );
    $elements[] = $submit;

    $this->addElements( $elements );
  }
}

So, basically, I pass one of the class constants to it's constructor. And based on that value, I determine what elements are needed for the form, and how the elements should be rendered.

For instance, for create you could have a select dropdown form field where you would choose a Locale, where for delete this would be a hidden field (not shown in my example btw).

Hope this has given you some ideas.

PS:
In one of the selected viewscripts you could then simply show the value of an element (along with rendering the hidden element too), with something like:

<?
  $form = $this->element;
?>

... some html

// let's presume id and locale are hidden form fields for current form type 
// (Cms_Form_Page::FOR_UPDATE for instance)
<?= $form->id->renderViewHelper(); ?>
<?= $form->locale->renderViewHelper(); ?>

// and here we simply output the current locale value
// of course, you should have populated the values in the form somewhere first
<dt>Current locale:</dt>
<dd><?= $form->locale->getValue(); ?></dd>

...etc

So, I think you'ld be best of with using viewscript decorators for the form, or you could roll your own form element decorator that renders the hidden field (if neccesary) and simply shows it's value in some html tag.


Hector from Nabble, show me this, which seems to be the best way:

class Default_View_Helper_FormView extends Zend_View_Helper_Abstract
{
    public function formView(Zend_Form $form)
    {
        $html = "<dl>";
        foreach ($form->getElements as $element) {
            $html .= "<dt>{$element->getLabel()}</dt>";
            $html .= "<dd>{$element->getValue()}</dd>";
        }
        $html .= "</dl>";
        return $html;
    }
}


I'm not sure if I understand, but I think that for the view option you can just fetch the data from your model. No need to access them through Zend_Form.

But if you want the make your form read-only, you can add readonly (setAttrib('readonly', 'readonly')) attribute to your elements.


Made a couple minor additions to the accepted answer to cover common elements that may be special cases:

class Default_View_Helper_FormView extends Zend_View_Helper_Abstract
{
  public function formView( Zend_Form $form )
  {
    $html = '<dl>';

    foreach ( $form->getElements() as $element ) {

      if( $element instanceof Zend_Form_Element_Submit ) {
        continue;
      }

      $html .= '<dt>' . $element->getLabel() . '</dt>';

      $value = $element->getValue();

      if( $element instanceof Zend_Form_Element_Checkbox ) {
        $value = ($value) ? 'Yes' : 'No';
      }
      else if( $element instanceof Zend_Form_Element_Select ) {
        $value = $element->getMultiOption($value);
      }

      $html .= '<dd>' . $value . '</dd>';
    }

    $html .= '</dl>';

    return $html;
  }
}


The only problem with the accepted answer is that you're creating all the elements and then ignoring them.

Using the control logic from fireeyedboy's answer, you could instead switch all the elements to Zend_View_Helper_FormNote which does the same thing.

Just depends on if the optimization matters.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜