Change proposal for Form Submission

Sunday, January 9th, 2011|Brainstorming, Version 4|by Romans

Agile Toolkit’s Form implementation comes a long way from probably 2006. There were some changes along the way and currently we are looking to implement a new default way of form submission. Please provide your feedback.

Change Request – $form->isSubmitted();

In the future – all the major changes in the Framework which might have impact on how you are writing your applications – will have to be announced through this Blog. Currently I am looking to submit a change which will add new way to check for form submission. But in order to understand what’s wrong with the current method, let me go through a bit of history.

Current way to submit a form

Currently the following code is used to on form submission.

[php]
$f=$this->add(‘Form’);
$f->addField(‘text’,'hello’);
$f->addSubmit(‘Ok’);
if($f->isSubmitted()){
$this->js()->univ()
->successMessage(‘Entered: ‘.$f->get(‘hello’))
->execute();
// code here will be executed if JavaScript is not supported
}

[/php]

This approach have a number of benefits:

  • Form automatically verifies if it was submitted, validates itself and if successful, isSubmitted() will return true.
  • Multiple forms on the page are supported, where any can be individually submitted
  • Allows for transparent AJAX support and allows backwards-compatibility with no-ajax code.
  • Very compact, no need to re-define form class.

Other framework comparison

If compared with other frameworks such as Zend, CakePHP, Yii, most of them would not perform automatic form submissions at all. They seem to follow a common pattern of request->isPost(), form->loadData($post), if(form->validate()). They wouldn’t help you with multiple forms on the page and developer have to call validation call manually.

By any comparison, current implementation in Agile Toolkit is much more intuitive and developer-friendly. Still it can be improved.

(If I have missed some important details on those frameworks, please point them out in the comments)

Downsides of current implementation.

  • if your code spans across multiple functions, it’s impossible to verify form submission several times. Even if you call isSubmitted() several times, inside first look, calling execute() will terminate your program.
  • you need to maintain two codes – one for the AJAX and another for non-ajax compatibility. Often second code is omitted, which leads to some weird results – isSubmitted() is called, but execute shows javascript string to the user.

Proposed improvement

The new way of handling submissions would be:

[php]
$f=$this->add(‘Form’);
$f->addField(‘text’,'hello’);
if($f->isSubmitted()){
// $f->displayFieldError(‘hello’,'sample error message’);
$f->successMessage(‘Entered: ‘.$f->get(‘hello’));
// alternatively
//$f->redirect(‘success’);
}
[/php]

This default approach would be the suggested use of the form. However it would rely on our existing powerful JS frameworks and could allow to do many other powerful things.

Proposed implementation

Calling functions displayFieldError, successMessage or redirect() would be mapped into $f->js(‘submitted’)->atk4_form(‘displayFieldError’), $f->js(‘submitted’)->univ()->successMessage() and $f->js(‘submitted’)->univ()->redirect();  Of course developer can automatically add chains for event “submitted”. When initialization is completed and when existing form::submitted() function is triggered – it will execute those chains if they exist. On other hand – if JS is not being supported, this will allow us to degrade properly and maintain backwards compatibility.

With this approach functions such as successMessage and redirect will not terminate execution. That means you can call isSubmitted() several times. You can chain multiple actions to be executed. The resulting actions will be performed when form’s submitted() method is called.

More advanced example:

[php]
$f=$this->add(‘Form’);
$f->addField(‘text’,'document_no’);
$f->addField(‘text’,'subject’);
if($f->isSubmitted()){
if(strpos($f->get(‘subject’),’@')){
$f->displayFieldError(‘subject’,'Must not contain @’)->execute();
}elseif(strpos($f->get(‘subject’),’#')){
$f->displayFieldError(‘subject’,'Must not contain #’)->execute();
}
$f->update();
$f->successMessage(‘Added: ‘.$f->get(‘subject’)); // automatically secured against injections
$f->js(‘submitted’, $f->getElement(‘document_no’)->js()->set($f->get(‘document_no’)+1) ); // increment value in form
}
[/php]

Benefits

  • Even cleaner form syntax
  • Built-in compatibility with non-javascript forms
  • Calling successMessage multiple times will show the first message only. Calling displayFieldError multiple times will output multiple errors. Many developers have been waiting for this.
  • calling redirect() will stop execution instantly.
  • calling form->execute() will terminate program and execute form actions.
  • Developer can specify more actions to be executed on submissions through chaining on $f->js(‘submitted’). Any other chains (even $f->js(true)) will NOT be executed.

Implementation information

This enhancement will go into git / master branch and will be released under Agile Toolkit 4.1 branch along with other improvements.