MVC, Forms, and JavaScript
Moderator: General Moderators
- VirtuosiMedia
- Forum Contributor
- Posts: 133
- Joined: Thu Jun 12, 2008 6:16 pm
MVC, Forms, and JavaScript
At the risk of spawning a debate, I have a question. I've read in one of the threads here that 'forms are a special case' in MVC-style architectures. I can see why because you are required to process the forms and true MVC separation isn't always practical for doing so. I like the idea of separating the model, view, and controller for the most part, or at the very least separating the view from everything else, but is there a good solution for forms being as they constitute a large part of almost any web app you'll make? I'm not wedded to MVC for MVC's sake...I'm just looking for something practical.
Also, I was reading DZone today and I saw this article about writing two layers of MVC, one for the server and one for the browser (a combination of JavaScript, CSS, and HTML). I thought I would point it out and see what everyone thought about it.
Could perhaps a browser MVC pattern be something like:
HTML = Model
CSS = View
Javascript = Controller
Also, I was reading DZone today and I saw this article about writing two layers of MVC, one for the server and one for the browser (a combination of JavaScript, CSS, and HTML). I thought I would point it out and see what everyone thought about it.
Could perhaps a browser MVC pattern be something like:
HTML = Model
CSS = View
Javascript = Controller
Re: MVC, Forms, and JavaScript
I very much agree with the thought that forms don't fit well within classic, strict MVC. I think this is so because there are always two parts in any form based page: the HTML form itself and the processing behind it. Both these parts are naturally coupled together so tightly that it hardly makes sense to divide them just to fit some ideal of 'cleanliness' within MVC. In this sense, the pseudo-MVC style that .net uses, with their code-behind pages and their tight coupling of view and controller, actually makes a lot more sense to fit the form processing problem. Much of common form processing and validation is actually cleaner and more explicit when described in a declarative way (ie: via XML in your view), and this is actually how a number of pragmatic frameworks handle it.
As far as the browser MVC, I have heard that comparison before and it seems a little bit far fetched to me, except for the most complicated, client-heavy ajax applications. I don't really see the benefit of seeing the client layer as an "MVC within an MVC"

As far as the browser MVC, I have heard that comparison before and it seems a little bit far fetched to me, except for the most complicated, client-heavy ajax applications. I don't really see the benefit of seeing the client layer as an "MVC within an MVC"
Spawning a debate is a noble goal, in my opinion, never a riskAt the risk of spawning a debate...
Re: MVC, Forms, and JavaScript
I completely agree that forms don't fit well with MVC. A number of us here on the forums are working on a validation / filter chain method that goes something like this:
in the controller:
in the view (uses some form of helper to render form elements):
I've found that this method allows the most freedom in advanced form creation (most forms are not this repetitive and simple) as well as uses the least code possible to get the job done. But... that's just me. 
in the controller:
Code: Select all
$filters = new A_Filter_Set();
$filters->addFilter(new A_Rule_Trim()); // no specific form element specified, so apply to all
$rules = new A_Rule_Set();
$rules->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
->addRule(new A_Rule_Email('email', 'Please enter a valid email'));
if (is_post()) {
$data = $filters->filter($_POST);
if (!$rules->isValid($data)) {
$view->errors = $rules->getErrorMsg();
}
}
$view->render('account.phtml'); // view is a made-up view objectCode: Select all
<form method="post" action="<?php $this->url('/account') ?>">
<dl>
<dt><?php echo $this->formLabel('phone') ?></dt>
<dd><?php echo $this->formText('phone'); echo $this->errorMsg('phone', $this->errors) ?></dd>
<dt><?php echo $this->formLabel('email') ?></dt>
<dd><?php echo $this->formText('email'); echo $this->errorMsg('email', $this->errors) ?></dd>
</dl>
</form>Re: MVC, Forms, and JavaScript
Wether you need or want a separation depends on the situation I think. Maybe the reason that the MVC separation is not always followed with forms is because forms have so many "connections" between the layers.
But I think using your view/template layer like this will give a quite clean V separation and complete freedom in styling everything
And then when you manage to separate the form processing logic from the underlying models you've separated the M and C.
[edit] Ninja's example is nice
But I think using your view/template layer like this will give a quite clean V separation and complete freedom in styling everything
Code: Select all
<form action="/login/" method="post">
<fieldset>
<div>
<label>Username</label>
<input type="text" name="username" value="<?php echo htmlentities($username, ENT_QUOTES, 'UTF-8'); ?>" size="20" class="text" />
<td><span class="error"><?php echo $unerrmsg; ?></span>
</div>
<div>
<label>Password</label>
<input type="text" name="password" value="" size="20" class="text" />
<span class="error"><?php echo $pwerrmsg ?></span>
</div>
<div>
<input type="submit" name="submit" value="Log in"/>
</div>
</fieldset>
</form>
[edit] Ninja's example is nice
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: MVC, Forms, and JavaScript
I would be interested in knowing where someone said that forms are a special case in MVC. I don't think they are. What makes them a special case or not doable in MVC?VirtuosiMedia wrote:At the risk of spawning a debate, I have a question. I've read in one of the threads here that 'forms are a special case' in MVC-style architectures. I can see why because you are required to process the forms and true MVC separation isn't always practical for doing so.
The problem with forms is mainly that they are not fun so programmers want to take shortcuts to avoid the pain. Nothing wrong with that, but what makes forms a 'special case' to me is that every shortcut leads to even more pain as the problem changes or gets more complex. Usually a programmer can take a shortcut and maintain that style -- but not forms.VirtuosiMedia wrote:I like the idea of separating the model, view, and controller for the most part, or at the very least separating the view from everything else, but is there a good solution for forms being as they constitute a large part of almost any web app you'll make? I'm not wedded to MVC for MVC's sake...I'm just looking for something practical.
The main question with forms is whether you consider the form data to be in the Presentation layer or the Domain layer -- meaning in the Controller or the Model. I should note that all the shortcuts involve making the form part of the Controller. That provides the most immediate pain relief, but causes the most problems later. Also there is the question of whether the form itself is a Model separate from the Model in the domain where it loads/saves its data from/to.
I don't think you have your M, V and C quite right. They will all be some Javascript probably. And adding a MVC layer in the client really does not change the design and responsibilities of the server side form code.VirtuosiMedia wrote:Also, I was reading DZone today and I saw this article about writing two layers of MVC, one for the server and one for the browser (a combination of JavaScript, CSS, and HTML). I thought I would point it out and see what everyone thought about it.
The next step past Ninja's example is to combine things like this (but you should be able to do it both ways):
Code: Select all
$form = new A_Model_Form();
$form->addFilter(new A_Rule_Trim()) // no specific form element specified, so apply to all
->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
->addRule(new A_Rule_Email('email', 'Please enter a valid email'));
if ($request->isPost()) {
if (! $form->isValid($request)) {
$view->errors = $form->getErrorMsg();
}
}
$view->render('account.phtml'); // view is a made-up view object(#10850)
Re: MVC, Forms, and JavaScript
I forgot to mention in my example that (like arborint pointed out) sometimes validation data might need to come from the model, or more often, some needs to come from the model and some needs to be added or removed on an action-by-action basis. That's why I like to add a getRules() and getFilters() method to my model so that it can add any bit of filtering / validation it needs to before you actually validate, for example:
I like this because it allows me to pull validation from any source I want. A good example is when you have an "edit user" and a "my account" page. I usually don't allow users to change their own username, but the admin can. So I would do this:
In the model
in the controller's "edit user" action for admin:
See how that works?
Code: Select all
$myModel = new MyModel(); // made-up model object
$filters = new A_Filter_Set();
$filters->addFilter(new A_Rule_Trim()) // no specific form element specified, so apply to all
->addFilter($myModel->getFilters()); // getFilters() returns an A_Filter_Set() object which can be added just like a regular filter to addFilter()
$rules = new A_Rule_Set();
$rules->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
->addRule(new A_Rule_Email('email', 'Please enter a valid email'))
->addRule($myModel->getRules()); // getRules() returns an A_Rule_Set() object which can be added just like a regular rule to addRule()
if (is_post()) {
$data = $filters->filter($_POST);
if (!$rules->isValid($data)) {
$view->errors = $rules->getErrorMsg();
}
}In the model
Code: Select all
class myModel {
public function getRules($admin = false) {
$rules = new A_Rule_Set();
$rules->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
->addRule(new A_Rule_Email('email', 'Please enter a valid email'))
return $rules;
}
}
Code: Select all
$myModel = new MyModel();
$rules = new A_Rule_Set();
// special rules for this action
$rules->addRule(new A_Rule_UsernameAvailable('username', $this->getPk(), 'The username you requested has already been taken. Please try another one.'));
->addRule(new A_Rule_UsernameWellFormed('username', 5 'Please provide a username at least 5 characters in length with at least one capital letter and at least one number.'));
// standard rules all myModel actions use
->addRule($myModel->getRules());
- VirtuosiMedia
- Forum Contributor
- Posts: 133
- Joined: Thu Jun 12, 2008 6:16 pm
Re: MVC, Forms, and JavaScript
Here is where I got the 'forms being a special case in MVC' quote from.arborint wrote:I would be interested in knowing where someone said that forms are a special case in MVC. I don't think they are. What makes them a special case or not doable in MVC?
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: MVC, Forms, and JavaScript
I don't think Kieran meant 'special case' in the sense I of 'unique' if you read the rest of his post. When you add a data element to a Model, you usually have to change the View to reflect that data. If a new element gets added to an XML feed then you will will need change your Model to hold that new element.VirtuosiMedia wrote:Here is where I got the 'forms being a special case in MVC' quote from.
Forms are certainly make the connection between the Model and View more obvious and immediate that other things. I think maybe that is what Kieran meant (but I try not to second guess Mr. FTW
Back to what I think was you initial question, I do think there are some very interesting possibilities with doing more in the client. The simplest would be to get out of the business of generating HTML on the server side. A Javascript library independent way for the server side to provide form information so it could initialize and render the form as needed would be really nice. Next would be doing client side validation would decrease load on the server -- another win.
If you are interested in this stuff, I know a project looking for someone to work on a client side forms solution.
(#10850)
- VirtuosiMedia
- Forum Contributor
- Posts: 133
- Joined: Thu Jun 12, 2008 6:16 pm
Re: MVC, Forms, and JavaScript
I'm actually pretty close to having a clientside validation script done using MooTools. There are few issues that still need to be worked out across browsers. I've been working on another project, but I should finish that up this week hopefully and I'll be able to get back to it. Once I get the issues solved, I'll opensource it. You guys are welcome to make use of it if you want. There aren't any onclick, onsubmit, or onblur events that you have to put into the form elements...those are all handled by the script. It will allow you to specify whether or not the error messages are above or below the input, the label and the input both have error and success states that are controllable by CSS, you can choose to disable the submit button if an error occurs, you can specify customized error messages for each validation check, and you will be able to choose from a few preset validations or enter your own regex. The syntax will be similar to the following:arborint wrote:A Javascript library independent way for the server side to provide form information so it could initialize and render the form as needed would be really nice. Next would be doing client side validation would decrease load on the server -- another win.
If you are interested in this stuff, I know a project looking for someone to work on a client side forms solution.
Code: Select all
<script type="text/javascript">
window.addEvent('domready', function(){
var form = new Validator('form');
form.empty('firstName', 'You must enter a first name');
form.alpha('firstName', 'Name must be alphabetic');
form.empty('email', 'You must enter an email');
form.email('email', 'The email address you entered is not valid');
form.validateRegEx('hello', 'helloInput', 'You must type hello');
});
</script>
- inghamn
- Forum Contributor
- Posts: 174
- Joined: Mon Apr 16, 2007 10:33 am
- Location: Bloomington, IN, USA
Re: MVC, Forms, and JavaScript
I don't see forms as a special case of MVC at all. In my stuff I treat forms like any other HTML markup. I think of forms as a way to tell the user where to send their data, and what data the server accepts. It is very much a web application as a service.
The view has the form markup no different from any other view in the system. You still have to escape any data you display.
The controller creates the view and tells it to render itself. But also looks for and handles user input coming from GET and POST. By handle, I mean that it makes sure the user is allowed to send the data they;re sending. It then instantiates the model and passes all the data to the model. It may also tell the model to save itself.
The model handles all the data validation.
As far as the controllers are concerned, they don't care whether the data came from the user interacting with an HTML form and hitting submit, or if the user used some AJAXy thing to send data. It is only concerned with reading the incoming data and passing it along to the model.
The same controller becomes a service. One that can read and respond to HTML as well SOAP, JSON, XML-RPC, or plain text. It's always just reading the input a view and telling the view to render.
The view has the form markup no different from any other view in the system. You still have to escape any data you display.
The controller creates the view and tells it to render itself. But also looks for and handles user input coming from GET and POST. By handle, I mean that it makes sure the user is allowed to send the data they;re sending. It then instantiates the model and passes all the data to the model. It may also tell the model to save itself.
The model handles all the data validation.
As far as the controllers are concerned, they don't care whether the data came from the user interacting with an HTML form and hitting submit, or if the user used some AJAXy thing to send data. It is only concerned with reading the incoming data and passing it along to the model.
The same controller becomes a service. One that can read and respond to HTML as well SOAP, JSON, XML-RPC, or plain text. It's always just reading the input a view and telling the view to render.
Re: MVC, Forms, and JavaScript
I very much agree with inghamn. In addition, when using an MVC structure form reuse becomes much easier. Some actions use essentially the same form (such as an add / edit action for a content item, or registration form / editing user profile), so reusing the same template with different controller actions / model methods can save much time on development and increase consistency all around.
- VirtuosiMedia
- Forum Contributor
- Posts: 133
- Joined: Thu Jun 12, 2008 6:16 pm
Re: MVC, Forms, and JavaScript
So should the actual form itself be generated by the class or should it be written out in full HTML with snippets of PHP to generate values, errors, and such? I think that may be my root question more than anything else in regards to forms and MVC. I might be wrong in my definition, but the way I understood it, using MVC you are usually trying to separate the view so it contains as little PHP as possible so that it basically serves as an HTML template, which is much easier to edit by more people than having it generated by a class.
Re: MVC, Forms, and JavaScript
I would say that if you want a clean separation you would write the form in full HTML with little snippets of PHP, only echoing out the values and error messages. See the short example I gave earlier in the thread.
The point is not to remove all PHP (although it's possible with template systems as smarty), but to remove controller and/or model logic and only keep small presentation code.
The point is not to remove all PHP (although it's possible with template systems as smarty), but to remove controller and/or model logic and only keep small presentation code.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: MVC, Forms, and JavaScript
It can be either. The decision is dictated by the problem being solved and your personal taste.VirtuosiMedia wrote:So should the actual form itself be generated by the class or should it be written out in full HTML with snippets of PHP to generate values, errors, and such? I think that may be my root question more than anything else in regards to forms and MVC.
This is one of the major misconceptions about MVC. The View is the part of the Presentation Layer that is responsible for rendering the Model is a specific way. There can be may Views for a Model. The View often has much more code than the Model does in fact, because the output is often more complex than the Model's data and logic. You are free to put as much PHP code into your Views as necessary. Think if all the code in modern template libraries -- that is all View code. All the code that uses a template library in your app is View code as well. People often put that code in the Controller (which is also in the Presentation Layer) so the View code is in a Controller action.VirtuosiMedia wrote:I might be wrong in my definition, but the way I understood it, using MVC you are usually trying to separate the view so it contains as little PHP as possible so that it basically serves as an HTML template, which is much easier to edit by more people than having it generated by a class.
(#10850)
Re: MVC, Forms, and JavaScript
To echo what some of the folks have already said... I don't think forms are particularly a special case, you just need a flexible helper for outputting validation errors. I tend to write form-heavy applications on CodeIgniter and don't really have a problem with code separation.
If you wanted to be pedantic about no PHP in your view then you could surely solve the problem with clever use of a template engine?
If you wanted to be pedantic about no PHP in your view then you could surely solve the problem with clever use of a template engine?