Reputation: 321786
I'm still somewhat confused by how MVC is supposed to work.
Lets say I have a website selling widgets. I have a listing page, /widgets/list
and a product page /widgets/product/123
.
Both of these can use the widget
controller and call the list
and product
methods - simple enough so far. Lets say I also have several other controllers for various things.
Now I add a newsletter signup box into my header - i.e. on every page of the site.
How is this going to work? I get the idea that it should submit to /newsletter/signup
But what happens if there's an error (say you didn't fill in your email address correctly)? It should show whatever page you were on (e.g. /widgets/list
) but the newsletter
controller needs to run. The widget
controller doesn't know about the newsletter
controller so I can't put the code there... How is this supposed to work?
Edit: No AJAX please - I can understand that more easily. Consider this the fallback when javascript is disabled.
Edit 2: Any examples or tutorials covering this kind of thing would be much appreciated
Edit 3: Is it allowable for a view to call an action? For example the header might call Newsletter->index()
Upvotes: 9
Views: 485
Reputation:
There is a good ASP.net MVC centric tutorial describing methods to include widgets (reusable components) in an MVC environment.
The basic idea is to set up widgets with their own request pipeline - not amalgamate them into a combined controller/view which would defeat the maintainability of MVC.
Upvotes: 1
Reputation: 1733
How about adding a hidden field to the page submitting to the /newsletter/signup controller with the url of where to go after the controller is finished i.e. the current page (or you could use the referer http header).
This controller then adds a list of error messages or a success message to a list of objects to be rendered by the view before forwarding on to the controller specified by the hidden field above. This controller then adds it's list of objects to be displayed in the view (eg. list of widgets).
Then in the view, you can display the error messages from the newsletter controller if present.
Upvotes: 0
Reputation: 32374
I don't see why the error message for the newsletter box thats on every page, has to be rendered in the same page. If you have a page which posts to another action - completely unrelated to the current view (for example - search) then there is no reason for the error message to be shown in the original page. Would you show the success message on the same page? Where would that be handled?
Error messages for the newsletter form should be shown in a view dedicated to the newsletter. For example, see how its done in Stackoverflow - go into the search box and type nothing, simply hit enter. This is a kind of error since you did not specify what you want to search for. Stackoverflow will then take you to a different page that explains how search work.
Now why did it do that? The reason is simple - the user was on some page and chosen to engage in an activity that is not related to the current page, so there is no reason to keep them there.
Upvotes: 6
Reputation: 66871
What I do is have each form post to itself. In the controller, I check to see if the post variable is set; if so, I do validation. If the validation succeeds, I do a redirect to another page. If it fails, the form page just gets reloaded with error messages. This makes it easy and reduces code duplication. See here:
**in controller**:
If post variable is set:
validate form
if form is validated:
redirect to new page (or whatever)
else:
add error messages to the $data variable of the view
endif
endif
//$data contains whatever information you'd normally pass to the view.
//if there was a validation error, the messages are added to the $data variable
show view with $data variable
As you can see, the flow always falls through to the single view-loading statement. However, if validation succeeds, you are whisked away to another page.
Upvotes: 0
Reputation: 47637
For widgets that are supposed to return some validation errors etc. - use partial requests (or subcontrollers from MvcContrib) + AJAX.
Upvotes: 0
Reputation: 4460
Add a field to the newsletter form, that stores the URL of the current page. When an error occurs during submission of the newsletter, retrieve the URL and redirect to that page. Providing that you put the error information in the correct place, it should be picked up by the newsletter form which, you say, is included in every page.
Upvotes: 1
Reputation: 28235
My MVC experience is more practical and less "what the book says", but here goes:
You'd have a base controller class (in CakePHP - which is what I'm most familiar with - it's called AppController
) which is subclassed by all other controllers. This class would implement all of the "global" stuff you're talking about.
Practical example:
In my AppController
class, the framework defines a beforeFilter()
callback which is executed essentially on each page load. This is where I'd check to see if the signup form had been submitted and handle it appropriately. If the signup took a crap somehow, I'd add something to the session indicating as much and my view would simply check for the existence of a list of errors originating from the newsletter model and, if they're there, show them.
This is probably a little heavier on nuts and bolts and lighter on theory than you were asking for, but I have no formal training in any of this crap so there's my best :)
Upvotes: 0
Reputation: 328760
You must put the error message in some global place where the page controller (which includes the "subcontrollers" newsletter
) can pick it up.
In case of AJAX, you can have the newsletter
controller talk to the DIV
in which is it visible (since you're not reloading the whole page). For that, you'll need a piece of JavaScript in the page that is called when the AJAX request finishes which takes the string and puts it where ever you want it.
Upvotes: 0