Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File element decorator issue #6

Closed
perfection opened this issue Mar 27, 2012 · 10 comments
Closed

File element decorator issue #6

perfection opened this issue Mar 27, 2012 · 10 comments

Comments

@perfection
Copy link

First of all thanks for the great work.
Warning: Exception caught by form: No file decorator found... unable to render file element
Stack Trace:
#0 C:\Program Files (x86)\Zend\www\imob3\www\library\Twitter\Bootstrap\Form\Decorator\FormElements.php(79): Zend_Form_Element_File->render()
#1 C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Form\DisplayGroup.php(920): Twitter_Bootstrap_Form_Decorator_FormElements->render('')
#2 C:\Program Files (x86)\Zend\www\imob3\www\library\Twitter\Bootstrap\Form\Decorator\FormElements.php(79): Zend_Form_DisplayGroup->render()
#3 C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Form.php(2904): Twitter_Bootstrap_Form_Decorator_FormElements->render('')
#4 C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Form.php(2920): Zend_Form->render()
#5 C:\Program Files (x86)\Zend\www\imob3\www\application\modules\admin\views\scripts\agenti\add.phtml(1): Zend_Form->__toString()
#6 C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\View.php(108): inclu in C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Form.php on line 2925

config.ini

autoloaderNamespaces[] = "Twitter"

Everything else works.

@theUniC
Copy link
Contributor

theUniC commented Mar 27, 2012

At a first glance, does not seem to be an error from the decorators. Can you paste the snippet of code that causes the error?

@perfection
Copy link
Author

sure

setMethod("post"); $nume = new Zend_Form_Element_Text("nume"); $nume->setLabel("Nume:") ->setDescription ("Introduceti Numele Agentului") ->setRequired(true); $prenume = new Zend_Form_Element_Text("prenume"); $prenume->setLabel("Prenume:") ->setDescription ("Introduceti Prenumele Agentului") ->setRequired(true); $telefon = new Zend_Form_Element_Text("telefon"); $telefon->setLabel("Telefon:") ->setDescription ("Introduceti Telefonul Agentului") ->setRequired(true); $parola = new Zend_Form_Element_Password("parola"); $parola->setLabel("Parola:") ->setDescription ("Introduceti Parola Agentului") ->setRequired(true); $poza = new Zend_Form_Element_File("poza"); $poza->setLabel("Poza Agent:") ->setRequired(true) ->addValidator('Count', false, 1) ->setDestination(APPLICATION_PATH . '/../public/imagini/agenti') ->addValidator('Extension', false, 'jpg'); $submit = new Zend_Form_Element_Submit("adauga"); $submit->setLabel("Adauga") ->setAttrib ( 'class', 'btn btn-primary' ) ->setIgnore(true); $reset = new Zend_Form_Element_Reset ( "reset" ); $reset->setLabel ( "Reset" )->setAttrib ( 'class', 'btn' ); $this->addElements(array($nume, $prenume, $telefon, $parola, $poza, $reset, $submit)); $this->addDisplayGroup ( array ('nume','prenume','telefon','parola','poza'), 'group', array ('legend' => 'Adauga un Agent' ) ); $this->addDisplayGroup ( array ('adauga', 'reset' ), 'actions', array ('disableLoadDefaultDecorators' => true, 'decorators' => array ('Actions' ) ) ); } ``` }

@perfection
Copy link
Author

I have found a fix
In file Twitter/Bootstrap/Form/Decorator/FormElements.php

I added the code below at line 75

        if ($item instanceof Zend_Form_Element_File) {
            $item->setDecorators ( array (

            array ('FieldSize' ), array ('File' ), array ('ElementErrors' ), array ('Description', array ('tag' => 'p', 'class' => 'help-block' ) ), array ('Addon' ), array ('HtmlTag', array ('tag' => 'div', 'class' => 'controls' ) ), array ('Label', array ('class' => 'control-label' ) ), array ('Wrapper' ) )

             );
        }

@perfection
Copy link
Author

Quick update since my IDE reformated the code and I ended up putting the wrong line number,
The snippet should be inserted at line 78
This is how it looks in context

        // Check if the element is disabled
        if ($item instanceof Zend_Form_Element && null !== $item->getAttrib('disabled')) {
            $class = $item->getAttrib('class');
            $item->setAttrib('class', $class . ' disabled');
        }
        if ($item instanceof Zend_Form_Element_File) {
            $item->setDecorators ( array (

                    array ('FieldSize' ), array ('File' ), array ('ElementErrors' ), array ('Description', array ('tag' => 'p', 'class' => 'help-block' ) ), array ('Addon' ), array ('HtmlTag', array ('tag' => 'div', 'class' => 'controls' ) ), array ('Label', array ('class' => 'control-label' ) ), array ('Wrapper' ) )

            );
        }
        $items[] = $item->render();

@theUniC
Copy link
Contributor

theUniC commented Mar 27, 2012

The intention of the Twitter_Bootstrap_Form_Decorator_FormElements class is to display all the form body accordingly to Twitter's Bootstrap markup, but no to add any extra decorators to the existing elements in the form, before rendering. These decorators should be added elsewhere.

@perfection
Copy link
Author

My bad, I just found out that that's normal for Zend's Image, Captcha and File elements.

@theUniC theUniC reopened this Mar 27, 2012
@theUniC
Copy link
Contributor

theUniC commented Mar 27, 2012

For sure, the invocation is correct. But it's not placed in the right place.

The issue has the origin on the base form class Twitter_Bootstrap_Form which is overriding all the decorators in order to set up Twitter Bootstrap's markup properly. The Zend_Form_Element_File form element needs at least one decorator that implements the Zend_Form_Decorator_Marker_File_Interface to be rendered, but since the decorators are being overriden an Exception is thrown because no decorator is found that implements the interface.

I've added a new element, the file element that checks if at least one decorator that implements the Zend_Form_Decorator_Marker_File_Interface has been added. If no one found, it adds the decorator. That should be enough to fix the rendering of the file form element.

In order to set up the file form element properly, you'll have to use the class Twitter_Bootstrap_Form_Element_File or the method addElement of the Zend_Form class (this is the recommended way in order to make use of the internal plugin loaders)

<?php

class Form_AddAgent extends Twitter_Bootstrap_Form_Horizontal 
{
  public function init ()
  {
    $this->setMethod("post");

    $this->addElement('text', 'nume', array(
      'label'      => 'Nume:',
      'description' => 'Introduceti Numele Agentului',
      'required' => true
    ));

    $this->addElement('text', 'prenume', array(
      'label'      => 'Prenume:',
      'description' => 'Introduceti Prenumele Agentului',
      'required' => true
    ));

    $this->addElement('text', 'telefon', array(
      'label'      => 'Telefon:',
      'description' => 'Introduceti Telefonul Agentului',
      'required' => true
    ));

    $this->addElement('password', 'parola', array(
      'label'      => 'Parola:',
      'description' => 'Introduceti Parola Agentului',
      'required' => true
    ));

    $this->addElement('file', 'poza', array(
      'label'      => 'Poza Agent:',
      'description' => 'Introduceti Telefonul Agentului',
      'required' => true,
      'destination' => APPLICATION_PATH . '/../public/imagini/agenti',
      'validators' => array(/*add your validators*/)
    ));

    $this->addElement('submit', 'adauga', array(
      'label'      => 'Adauga',
      'ignore'    => true,
      'buttonType' => Twitter_Bootstrap_Form_Element_Submit::BUTTON_PRIMARY,
    ));

    // You don't have to add the class "btn", since Twitter_Bootstrap_Form_Element_Submit will
    // handle it for you
    $this->addElement('submit', 'reset', array(
      'label'      => 'Reset'
    ));

    $this->addDisplayGroup(array('nume', 'prenume', 'telefon', 'parola', 'poza'), 'group', array('legend' => 'Adauga un Agent' ));
    $this->addDisplayGroup(array('adauga', 'reset'), 'actions', array('disableLoadDefaultDecorators' => true, 'decorators' => array ('Actions' ) ) );              
  }
}

Hope this will help!

@perfection
Copy link
Author

Thanks, that really helps!

@jimmykane
Copy link

This is still present in the v3 Of bootstrap

@jimmykane
Copy link

Any progress on this? Is this acknowledged ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants