Widgets And Forms

Hello everyone!

I am trying to create a login widget as selfcontained as possible, and I am facing some troubles while trying to manage validation errors. In general, I would have this problem with any form inside a widget view.

The login widget folder contains a LoginWidget class (extends CWidget), a LoginForm class (extends CFormModel) and a class LoginAction class (extends CAction) that handles the controller functionality (including a call to the validate method of the LoginForm object). The problems appear when there are validation errors, and the main page needs to be rendered again in order to show those errors to the user, since the widget doesn’t have the control of the LoginForm instance anymore.

AFAIK, there are three possible ways to do it (excluding AJAX):

  • In the run method of the widget I should call the validate method (double validation, since LoginAction also did it) using the $_POST[‘LoginForm’] information

  • I should not use LoginAction to handle the validation functionality. The run method from the widget should do it, and when the page renders again it will detect the validation errors (or redirect to the private home page otherwise)

  • LoginForm should be outside the widget directory, and the main page should pass an instance of the form via widget parameters.

I could have assumed some wrong premises and maybe I should consider other options

Could anyone show me the correct path?

Thanks in advance!

A possible solution:

Log in through Controller->init(). Yes, that is the init function of your custom base controller class located in components/Controller.php.

Then validate again through the widget.

This will allow you to remain on the same page, log in, and still be on that page. If the login fails the actual login won’t do anything, but the LoginForm in the widget will give the errors.

Hi Siquo,

Thanks for the reply. I finally came up with an approach that seems to work really great. No double validations, no unnecessary code processed and nearly no external dependencies outside the widget.

Controller.php




// Preloaded widgets array

public $components=array();



Action in controller:




// Initialization of components in action

$this->components['{widgetid}'] = $this->widget('{path.to.widget}', array(), true);



View:




<?php echo $this->components['{widgetid}'] ?>



Widget:




public $loginForm;


public function run() {

	...

        if (empty($this->loginForm))

        	$this->loginForm = new LoginForm;

        ...


        $this->render('{widget.view}');

}

    

public static function actions(){

        return array(

           '{actionid}'=>'{path.to.action}',

        );

}



Widget action:




public function run(){

	$loginForm = new LoginForm;

	$loginForm->attributes=$_POST['LoginForm'];

	

	$controller=$this->getController();

	

	if($loginForm->validate() && $loginForm->login()){

                ...

	} else{ 

		$controller->components['{widgetid}'] = $controller->widget('{path.to.widget}', array('loginForm'=>$loginForm), true);

		$controller->render('{view}');

	}

}



This way the widget is as self-contained as possible, and the controller part of the widget is encapsulated in the action associated to the widget. If validation errors are found, the widget pre-renders with that form, and the widget view handles the error treatment.