Loading Models and Model Relationships ====================================== Route Inheritance and the Index Route ------------------------------------- Now that we have the basics of creating models and saving them covered, we will look at actually using them in our application. Before we can do that, we need to do a bit of house-keeping and clean up the modules file structure. First we will generate a new route in which we will display the list of modules: .. code-block:: console $ yarn ember generate route modules/index Next, copy the content of the ``modules.hbs`` into the ``modules/index.hbs`` file. Then replace the content of ``modules.hbs`` with the following: .. code-block:: handlebars {{outlet}} Now test that the list of modules is still displayed as before. In the previous tutorial we simply created all our routes (and thus also the resulting templates) in the root directory. This is fine for small projects, but larger projects would very quickly become unmanageable. By creating the routes with a deeper structure (as with the "users/register" or "modules/index") the files linked to that route are also placed inside of directories, creating a cleaner project structure. When we have such a nested route ("modules/new"), the template for that route is placed within the ("modules") template, which is itself placed inside the "application" template: .. code-block:: text application modules new Thus when the user navigates to the "modules/new" route, they would see the content for that route together with the content for the "modules" route, which is of course not ideal. This is where the "index" route comes in. The index route (and template) is displayed when the user navigates to the parent route, without the user having to explicitly add the "index" to the URL. Thus if we define a "modules/index" route and navigate to the "modules" route, in practice the following structure is displayed: .. code-block:: text application modules index If as in the example above, we place all the content we want to display for the "modules" route into the "modules/index", then when we navigate to "modules/new" the structure shown above is used, but now the "modules" template only has the ``{{outlet}}`` in it and as a result the user only sees the "new" template and not both the "new" and the parent template. Models with Relationships ------------------------- First we need to define our new ``module`` model: .. code-block:: console $ yarn ember generate model module Then, we define the new model's properties, by updating the ``app/models/module.js``: .. code-block:: js import Model, { attr, belongsTo} from '@ember-data/model'; export default class ModuleModel extends Model { @attr code; @attr name; @attr semester; @belongsTo('user') teacher; } The model has three standard properties, but it also used the ``@belongsTo`` decorator to define a relationship between this model and another model. In this case we specify that there is a teacher property, which as its value has an instance of the "user" model. We will see how to use this in two steps. Loading models -------------- With the model defined, we can now fetch data from the server. Fetching data from the server is done in the ``model()`` function inside the route definition. Update the ``app/routes/modules.js`` and add the following code: .. code-block:: js import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default class ModulesRoute extends Route { @service store; model(params) { return this.store.query('module', params) } } If you reload the modules page, you will see that the sections and actions are now empty, this is because the data has been fetched from the server using our new model, and that has now attributes for those things. To implement the sections and actions again, we can call a ``getter`` function. Add the following code to ``app/models/module.js`` right below the ``belongsTo`` part: .. code-block:: js get sections() { return { dates: { title: 'Dates', icon: 'mdi mdi-calendar-clock', }, documents: { title: 'Documents', icon: 'mdi mdi-file-document-box-multiple-outline', }, exercises: { title: 'Exercises', icon: 'mdi mdi-test-tube', }, students: { title: 'TeilnehmerInnen', icon: 'mdi mdi-account-multiple', }, }; } get actions() { return { delete: { icon: 'mdi mdi-delete warning', title: 'Delete', action: 'delete', }, }; } When the app is built again, You should be able to see the content for the sections and actions again. The ``query()`` method, like the ``save()`` method actually returns a promise, rather than the data from the server. This means that initially Ember displays the list of modules without any modules. Then, when the data from the server becomes available, it automatically updates the template with the data that is now available. Thus after removing the fixed module definition you might occasionally see a brief white screen, while it is waiting for data. The ``params`` parameter, which contains the selected query parameters, is mandatory and is passed to the ``query()`` function, in order to ensure that the query is also sent to the server.