The viewLocator module collaborates with the viewEngine module to provide views (literally dom sub-trees) to other parts of the framework as needed. The primary consumer of the viewLocator is the composition module.
During composition, the framework calls into the viewLocator to obtain a view to render the current object with. It does this by calling viewLocator.locateViewForObject. Here's what that does:
First, the object is checked for a member function named getView. If this function exists, it is invoked and the object is given the opportunity to explicitly provide either a constructed DOM to be used as the view or a string to be interpreted as the view url/id. The result is passed to locateView which then either returns the DOM element or requires the view using its id and returns that. The getView method is not used in typical application scenarios. It exists for highly specialized scenarios where an object may need "one-off" control in determining which view to create or how the view should be created.
If there is no getView function, or if it returns null/undefined, then the object is inspected for a viewUrl property. If found, it is passed to locateView and processing continues as above to ultimately return a DOM element. Again, usage of this is expected to be rare.
If neither of the above explicit view declarations is found, then a convention is applied. This is the expected normative use. The first convention is to get the module's id. Durandal hooks into RequireJS and stores this information for all module instances. The module id is then passed to locateView which transforms it into a view id and returns the DOM sub-tree as described above. This allows for a very simple naming convention for view models and views. For example, a module named editCustomer.js will map to editCustomer.html.
If no module id is found, then an attempt is made to determine the object's type by examining its constructor. This type name is then mapped to a views folder and passed to the locateView function so processing can finish. This would mean that an object with a constructor named Customer would have a view url of views/customer.html. This is a last resort attempt to determine the view by convention and is not expected to be used normally.
The viewLocator allows for a very simple pattern of creating a module per view model or model and a corresponding view per module. Naturally, by using the composition module view resolution behavior can be customized in a variety of ways, but you may also want to customize the view locator directly with your own general mapping convention. There are three functions exported by the viewLocator which you can replace with your own logic in order to accomplish this:
convertModuleIdToViewId - This function does nothing by default which is why editCustomer.js is mapped to editCustomer.html (both have the same underlying id of editCustomer). Replace this function with your own implementation to easily create your own mapping logic based on moduleId.
determineFallbackViewId - As mentioned above, if no view id can be determined, the system falls back to attempting to determine the object's "type" and then uses that. This function contains the implementation of that fallback behavior. Replace it if you desire something different. Under normal usage however, this function should not be called.
translateViewIdToArea - When a view area is specified, it along with the requested view id will be passed to this function, allowing you to customize the path of your view. You can specify area as part of the locateViewForObject or locateView calls, but more commonly you would specify it as part of a compose binding. Any compose binding that does not include a model, but only a view, has a default area of 'partial'. That said, the default implementation of this function does no area translation.