In an MVC web app, where is the "right" place to put the code/logic to display a url link to a "next page" navigation control, the controller or the view? If I put it in the view, I have to pass to the view not only the data to be displayed on the current page but also data relating to the next page aka the page id of the next page. If I put it in the controller, the controller has to be aware of the navigation that the particular view is going to display. Neither approach seems very elegant to me. Is there another way?
I don't know if there really is a "right" way to do this. Here's some different ways that I would think about it though:
if a page of items is itself an object in the system, then the controller makes sense
if a page only exists within the view logic, then the view makes sense
if the view receives the entire list, then pagination is a presentation concept
if you foresee the need for different page sizes or organizations, then keep the logic out of the controller
My gut says that you should try very hard to keep all of the pagination logic in the view. This usually means that you want some way to calculate what the next page is based on the current page in the view or make the controller have some concept of a starting point in the result set. I usually do the latter - the view retrieves the data with an optional starting point that is the ID of the last item on the previous page. This way the pagination logic is in the view and the data retrieval is simple.
One of the things to watch out for is how you will handle retrieving the next page of data if the item that you are keying on no longer exists. In other words, if you link says "the first page following item A" and "item A" has been deleted, then you need to do something reasonable.
The controller should provide meta information about the data being displayed: number of pages and current page index are two that get what you need here. The navigation control should encapsulate the logic which, given those two pieces of information, can render the rest.
Related
In Angular, speed is the name of the game and rendering views with useful data as quickly as possible is always sought after. Angular allows us to reference data between the Controller and the View seamlessly using Angular's templating engine, which can make rendering views with correctly bound data lightning fast.
For example, lets say we have a simple Angular App which is simply a table of contacts with fields like First Name, Last Name, Phone, Email, and Address. We then want a Details view that appears when you click on a table row. We can wire up the <tr> to change views on click like this
<tr ng-repeat="contact in Contacts" ng-click="showDetails(contact)">
Then we can change the view and "instantly" show contact data in the new view. For example, we can change an <h1> at the top of the page to be Contact - John Smith using the data that was provided in showDetails.
While this data is being shown, more data can be retrieved from the server asynchronously that will then fill in the rest of the fields.
However, what do we do if we want to get to this details page directly from the url? If the contact table was sitting at /contacts and the details page was something like /contacts/detail/1 then attempting to go directly to /contacts/detail/1 would result in the <h1> above to be blank.
This is clearly because we did not use the showDetails() method to invoke the view and pass the clicked contact into it directly. In this case, we would need to take the contact id in the URL and run an AJAX request to get ALL of the data.
My question is, at what point do we draw the line between trying to make our views and data quickly accessible and making them robust?
Robust is a must.
So we need to start there. Then we can move forward to optimize and make data "quickly accessible", as you put it, as much as possible.
In order to do that, every view in an SPA that is directly correlated to a URL needs to be initially stateless. That basically means that a reload on any url will load the desired view correctly and completely.
We can get the best of both worlds by using nested routes. If every route loads only what it needs, but also draws on parent routes (loading them if necessary, or just using them if they have already been provided) then you can achieve both robustness and "quick accessibility" to data.
In your particular example, the base route would be contacts. Then there could be a nested route inside of that which would display the details of a particular contact, contacts/detail/{id}. Loading the base url would load the list of contacts, and loading the details view would load both the list of contacts and the details of a particular contact. To provide quickly accessible data when going to the nested view, we could include logic that checks to see if the parent view data is already loaded, and only load if necessary. Then when navigating from the contacts to the contacts/detail/{id} view, we could quickly display data from the parent view in the child view, while loading data specific to the child view. A reload at contacts/detail/{id} would simply load both. When navigating back to the parent, the parent data would already be loaded.
If you were to use something like ui-router to create complex routes, then you would not use showDetails() to alter the model, you would use showDetails() to alter the route. Then your model would set itself up based on the route, and your view would follow.
For example, you could have something like:
$scope.showDetails = function(contact) {
$state.go('contacts.detail', { contactId: contact.id });
};
Then the controller could use $stateParams to retrieve any data you wanted for the specific contact from the server (asynchronously using promises). You could also include your own flavour of caching/loading via services to manage things like performance if you found it necessary.
In cases where new items need to be added to a list via ajax, what is the biggest benefit of using something like Knockout.
So far what I have been doing is, on my view, use an editortemplate (with asscociated viewmodels) to render a list of items. Then to add a new item, I make a request to an action that loads a server-side viewmodel, and returns an EditorTemplte object which just gets appended to the list. Like this:
return Json(new { this.RenderPartialViewToString("MyEditorTemplate", model) });
The knockout way of doing things requires the implementation of another view model to display items, and then another template to display it. But doing it this way requires duplication of code since the view model has to be represented in 2 places: in the cserver side code and then the view for the knockout viewmodel. Isn't that bad practice?
Am I missing something, or understanding the purpose of knockout and MVVM?
The biggest benefit that you will see from Knockout is that you will not need to hit the server in order to add a new item to your list - everything happens client side. This has multiple benefits including:
You reduce load on your server.
You improve the end-user's experience.
You can keep multiple elements on the page up-to-date with your model without any server interactions.
Two great examples of this can be found at these Knockout tutorials:
Working with Lists and Collections
Loading and Saving Data
As far as duplicating code, if you take a look at those two tutorials, you'll notice that you don't need to duplicate code. For example:
Create a view to display your entire list.
To add a new item to the list, create a partial view that you load when you add a new item to the page - that partial view is bound to Knockout
When you submit the entire form, everything in that list will be submitted - including those items you added via Knockout.
Your ViewModel will be specific to your list item (you don't need to create an entire ViewModel for everything, necessarily). And your view is specific to a single list item.
Hope that's clear. Knockout is pretty straightforward and they have some great documentation and tutorials to help you move forward.
IMHO, the following is cleanest option for the architecture of knockout and asp mvc mixed together.
Have your ASP.net acting as a webservice and have knockout control all your view templating and logic.
Otherwise, yes there will be potential replication of viewmodels and having to refactor both front and backend code when you need to change your model.
My question is mostly conceptual about Backbone.js, but I can mock up some code if my question is unclear.
Consider a case where I have 2 sections on a website. A list of items as one view and another view that has a dropdown to select how the list of items should be sorted. Obviously, the list of items is associated with a collection of models that stores the actual data that populates the list. But I'm unsure the best approach for triggering the collection to be sorted differently when the other view's dropdown changes. Should I be changing the actual order of the collection, or just render the view in the order that I want in the view?
Also, is it a good idea to use a model for the dropdown to keep track of the state of the dropdown, and bind the list of items view to that model so that I know when to rerender the list of items?
You could take several roads here. Here's a few:
Use a router. The router would hold your views, or at least the top-level view (cleaner), and your dropdown view would trigger a route change, which would pass the information along to the view. Best if you want clean URLs.
Make a pointer to the list view in the dropdown view. When the dropdown view receives the change event, it explicitly tells the list view to update. (IMO a terrible approach, but listed here for completeness.)
Back everything with models. (Like you suggest in your last question.) The dropdown view would be backed by a model, and the list view could bind to that model's events. (Again, the list view still has to know about the dropdown model—not ideal.)
Make an event manager. When your dropdown recevies a change, you trigger 'sort' and anything that cares can listen to that event. This isn't a trivial solution but isn't overly complex either. Your list view could then register its intent to listen to the sort event with the event manager, thereby abstracting the actual view inside the event manager and away from the dropdown view.
1 & 4 are effectively the same thing, just depending on whether you want a router or not.
Basically my heuristic with these sorts of scenarios is "nothing should know about things it doesn't need to know about." Applied here, that means that your views shouldn't know about each other.
I am buiding a UI screen for editing the details of an Ecommerce Order. The model for my view (OrderModel) has everything I need (in properties that are also ViewModels), but the UI isn't designed to be able to edit all of it at once.
For example, one part of the UI is for customer data..another for order details, and another for tracking information, each having their own "Save" buttons.
I realize that I could use one giant form and use hidden form fields to populate the non-editable fields, making each "Save" button post all the data, but that smells bad.
I'd like to segment the editable chunks into smaller ViewModels that are posted and validated individually while retaining the strong typing but I'm unsure of how to achieve this in MVC3. Will I need partial views that are called from the primary view?
FYI, I'm using ASP.NET MVC 3 with Razor syntax and client side FluentValidation.
Partial Views are a good solution. You can pass different ViewModels to each partial view. But if only sections of the overall view are updated at a time I would not do a post back on the whole page. Instead I would use Ajax calls using JQuery/Javascript to update the individual information back to the controller. I would also look into something like Knockout.js to handle the data binding on the page.
I'm developing an app which has a large amount of related form data to be handled. I'm using a MVC structure and all of the related data is represented in my models, along with the handling of data validation from form submissions. I'm looking for some advice on a good way to approach laying out my controllers - basically I will have a huge form which will be broken down into manageable categories (similar to a credit card app) where the user progresses through each stage/category filling out the answers. All of these form categories are related to the main relation/object, but not to each other.
Does it make more sense to have each subform/category as a method in the main controller class (which will make that one controller fairly massive), or would it be better to break each category into a subclass of the main controller? It may be just for neatness that the second approach is better, but I'm struggling to see much of a difference between either creating a new method for each category (which communicates with the model and outputs errors/success) or creating a new controller to handle the same functionality.
Thanks in advance for any guidance!
My preference would be to create triplet Form-Controller-Model for every form displayed to the user. Whenever user clicks on 'Next' button on a form its controller should talk to the back end manager which takes care of dispatching submit request to the next form in chain. Vice verse if 'Back' button is clicked. Last form has a 'Finish' button which will go to the manager and pass the last bits of information.
This will avoid inheritance, make your code more robust and testing of forms possible in isolation.
My preference would be to keep it all in one controller. It keeps all the relevant processes for filling out the application/form in one place, although I'm not sure how "massive" you're talking about. If you do decide to split it out, I would not subclass off of the main controller, but just make a handful of independent controllers, perhaps related by name for ease of use down the road.