0

I have a question regarding the official Angular styleguide about feature modules.

Let's say i have a feature module person and a feature module cars. Now i want to display a table containing all persons. When clicking a table row the table should expand showing a car table containing all cars of a person. Now when clicking a car row i want the car table to expand displaying all persons owning such a car.

| Name   | Age       |
| Peter  | 25        |
| > Cars | Brand     | Model   |
|        | Toyota    | Corolla |
|        | > Persons | Name    | Age |
|        |           | Peter   | 25  |
|        |           | Fred    | 35  |
| Hans   | 28        |
| Fred   | 35        |

Therefore i have a circular dependency since person-table -> car-table -> person-table are coming from two different feature modules. Would it be considered okay to move person-table and car-table into a SharedModule in order to fullfill the use case?

LorisBachert
  • 283
  • 1
  • 2
  • 12
  • A shared module will not resolve the problem. A shared module inport some modules- pipe-directive, which are often used, and export them. It means, when you import the shared module, you directly import all the things imported/exported by the sharedModule. – Soukyone Jan 16 '20 at 13:09

1 Answers1

2

I prefer to follow the one component per module design pattern, and use lazy modules for features with a single main module bootstrapping everything.

The main module should have the least dependencies necessary to start the application as this improves loading performance, and the top level route should be lazy loaded. So when the application starts the first feature lazy loaded is the main application. All other lazy modules are child routes.

A lazy module should only have the outlet components and services (providers) needed for that feature. All the other visual components come from a shared folder that contains one component per module directories.

This design pattern does follow the design guide but has a finer grain of modules. It does create more boilerplate code and many more files, but there are both maintainability benefits and compile time benefits (i.e. tree shaking is far more effective).

A typical project structure for me:

src/app
+-- lazy
+-- main
+-- shared
  • /src/app/lazy contains subfolders of lazy modules.
  • /src/app/main contains the AppModule that is bootstrapped.
  • /src/app/shared contains subfolders of one component per module directories

A typical lazy module would be structure like this

src/app/lazy/feature
+-- OutletFeature
+-- feature.module.ts
+-- feature-routing.module.ts
  • /src/app/lazy/feature contains the module and routing
  • /src/app/lazy/feature/OutletFeature is target component for the lazy route.

The lazy feature would contain guards, resolvers and services. You can also add additional components if they are unique to the feature, but I try to keep this to a minimal, because often they end up getting re-used when a similar feature is added later.

The shared folder contains the components.

src/app/shared/Example
+-- Example/example.component.ts
+-- example.module.ts

Above is an Example component with a module of the same name. Following the component directory pattern a folder of the same name holds the component. Shared modules are not limited to a single component, but the consumer of the component should only expect to see one component exported by the module. In the example of a table, the shared component would be a table, but the module might contain inner components for the header, rows and footer. The idea is that the module is of a single purpose.

Everything above is an opinion, and the style guide offers a good pattern for a small project. I've used the above on several large scale applications and feel that it scales very well.

Angular Material library uses the one component per module pattern as an example. They have a custom build process which makes the structure of their source code a little confusing at first, but once you get into the components section everything is a single component.

https://github.com/angular/components

Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • Thanks for sharing this. It's a really interesting approach and i'll definitely give it a shot. Nevertheless i'll leave that question open in order to get some more opinions on this. – LorisBachert Jan 17 '20 at 08:02
  • After thinking about your approach for a while i think this will not solve my problem. Even if i have a single module for each of my tables i'll have a circular dependency like person-table-module -> car-table-module -> person-table-module – LorisBachert Jan 17 '20 at 08:37