Logical Pattern, Software Design Concepts
You definitely want to be thinking in terms of components, regardless of what language or framework you choose to use for implementation.
- Divide up your application into different views (perhaps one for each of the navigation menu elements).
- Subdivide each of these views further (as needed) based on what types of functions they serve. I like the way that Bootstrap's panels help you visualize this.
- Develop each of these components and give them names, like ContactList, ContactEdit, ContactView, etc. Develop HTML views and JavaScript, TypeScript or other language viewmodels for each of these components. Be sure to use MVC logic to separate your views from the data, using placeholders in the view to indicate where you will fill in the data. The views are like templates.
- Use your specific language or framework to link it all together.
Here is a great tutorial on Component-Based Software Architecture and Design.
Aurelia Component Logic
I'm currently using Aurelia, and since you mentioned it, we'll use the Aurelia framework as an example to illustrate the above principles. Best practice would be to create the components (for modularity and reuse) and then use the if.bind property to include them or not in the DOM.
Example:
<tenant-one if.bind="tenantA"></tenant-one>
<tenant-two if.bind="tenantB"></tenant-two>
Or to only show/hide each component from the view (but include all in the DOM), you would use show.bind instead of if.bind, but that seems to make less sense for your use case.
Aurelia Data Binding
Since I don't know what you actually hope to display here, the above code is based on your code snippet in the question. However, for similar views where only the data will change (like a template), you would bind the data from the parent to the child so that it can be displayed correctly. In Aurelia, this would look like this.
Example:
<tenant-view data.bind="tenantData"></tenant-view>
More Complex Example:
<tenant-view fname.bind="firstName" lname.bind="lastName" data.bind="tenantData"></tenant-view>
In each of these examples, you would need to develop 4 files. You would need the main (parent) container that has a view and a viewmodel. The viewmodel would be in charge of retrieving or accessing the tenant information and then passing it on to each of the child components. The child component would have its own view and viewmodel.
For example, the TenantView view (highly simplified) might be like this:
<template>
<p><strong>Tenant Name: </strong>${fname} ${lname}</p>
<p><strong>Additional Data: </strong>${data}</p>
<p if.bind="data.rentDue">Tenant's rent is due!</p>
</template>
And then the TenantView viewmodel (again, highly simplified) might be like this:
import { bindable, bindingMode } from 'aurelia-framework';
export class TenantView {
@bindable fname;
@bindable lname;
@bindable data;
}
Once you have this component created, you would then insert it (optionally) in the parent view, like this:
<template>
<h1>Contact View</h1>
<h2>${firstName} ${lastName}</h2>
<tenant-view if.bind="cat == 'tenant'" fname.bind="firstName" lname.bind="lastName" data.bind="contactData"></tenant-view>
<phone-numbers data.bind="contactData"></phone-numbers> <!-- another component -->
<page-footer></page-footer> <!-- another component -->
</template>