Aurelia is a great framework for a SPA, but one thing that is missing, I feel, is getting server-generated templates. By default, Aurelia uses the moduleId
to fetch a static HTML file.
Take this configuration:
router.configure(config => { config.map([ { route: ['','Welcome'], moduleId: './welcome' }, { route: ['About'], moduleId: './about } ]); });
When you navigate to #About
, two calls will be made:
If your view is at some other location, you can customize the ConventionalViewStrategy.convertModuleIdToViewUrl function:
ConventionalViewStrategy.convertModuleIdToViewUrl = function(moduleId){ return moduleId.replace('view-models', 'views') + '.html'; }
We can use this technique if we want to call an ASP.NET Controller and have it return a view. Why would you want to do this? Translations, performance, templates that differ per user, etc. I don’t know what your reason would be, but there are all kinds of web-apps out there. It’s unrealistic to think it wouldn’t come in handy or be necessary.
Back to the code.
Override the function as you see fit. Do this as part of your bootstrapping. This is how I did it, in my main app.js file:
import {ConventionalViewStrategy} from 'aurelia-framework'; ConventionalViewStrategy.convertModuleIdToViewUrl = function(moduleId){ if (moduleId === 'modules/invoice-generator') { return 'InvoiceGenerator'; } return moduleId + '.html'; }; export class App { configureRouter(config, router) { // your router config here } }
So now, if the path is #invoice-generator
, I will get the following two requests:
On the ASP.NET side, I now want to return the View associated with this InvoiceGeneratorController. The controller is easy enough:
public IActionResult Index() { var viewModel = new InvoiceGeneratorViewModel(); viewModel.SomeProperty = "SomeValue"; return View(viewModel); }
The View is a little bit special though. Notice how we set the Layout
property to null:
@{ Layout = null; } <template> <h1>Invoice generator</h1> @Model.SomeProperty </template>
Setting the Layout
to null is important. This ensures the response of the /InvoiceGenerator
call is the HTML template like you see it there, without the _Layout.cshtml
wrapped around it. But the @Model.SomeProperty
will still be replaced by the value you provided in your Controller.
Forget the Layout = null
line, and you will probably get errors like X was detected as System.Register but didn't execute
.
The one thing that I don’t like is the if-check in the convertModuleIdToViewUrl
-function. I find the way Angular handles this, with the templateUrl
-property, a cleaner solution. I’ve created a GitHub issue for this. There should be a viewstrategy
property in the setup of your router, but I couldn’t get it to work. Rob is looking into it.