Why more Angular Modules are Better than One

I recently reviewed some Angular code that uses one module.  The AppModule. To manage the entire code base.  And, this isn’t tiny code base.  The main excuse I’ve heard for this is that the code originated during the beta cycle, prior to NgModule being added to the framework.  I call it out as an excuse because once it was added, it was clear that we needed to have more than one module.  The fact that this code base doesn’t have more than one module shows a disregard for doing things right over doing things fast.  In the best case, it shows ignorance.

But, the larger question this code base raises for me is this: “Why are more modules better than fewer modules?”  After all, using one module obviously works.  Isn’t the fact that it works sufficient enough?

And here are three really good reasons to use more modules.

Why more Angular Modules are Better than One
Photo credit: goodrob13 on Visualhunt.com / CC BY

 

Avoid Component Collision

For discussion purposes, let’s say you have an application with two routes.  Each route allows you to edit different kinds of content.  You may be inclined to create some child components in each route to assist with your functionality.  In the process of doing this, you may end up with two components that have the same name.  Both as a class and as a selector.  If you are including everything in one mega module, you will need to artificially give the components different names.  However, if each route has its own module, you can declare the components in the declaration section of each module with the same name and each route will be able to call the appropriate component.  Components aren’t shared across modules until you export the component.  In that case, you would also want the component to live in a shared module where we would give it a more meaningful, generic, name that made sense as a shared module.

Lazy Loading

Once you’ve created modules for each of your routes, the next logical step in your development effort will be lazy loading the module.  Lazy loading provides more advantages than just the ability to load only what you need when you need it.  That’s just the most obvious gain.  Lazy loading also provides a separate context for @Injectables.  Once again, just like having the ability to isolate the components, by using modules in conjunction with lazy loading, we have the ability to have route specific @Injectables with the same name and each route/module will behave appropriately.

There is one caveat.  You can’t provide an @Injectable in a lazy loaded module and an application level module and expect things to work correctly.  And, if you are still using a framework like NgRX 2 that needs to have access to services, you’ll need to make your services globally available.  This is one of many reasons why I believe you should upgrade to NgRX 4 as soon as is possible.  This allows you to take full advantage of the Angular Lazy Loading capabilities and all their benefits.

Cleaner Code

Even if you’ve never seen a major application with one module, I’m sure you can imagine what a mess that module is.  I don’t think I really need to say much more about this.

For more on Angular Modules, I recommend this FAQ that the Angular team put together. This Medium article is also pretty good.

Attaching an Angular Child Component’s Form to a Parent

This past week I implemented a pattern I’ve been pondering for almost a year now.  I like to create rather modular and granular code such that if my data structures are nested, the components that represent them on the screen should be nested as well. The question becomes, how does one create a reactive form in a child component and attach that form to the parent form in a way that:

  1. Leaves the definition of the child form entirely in the child
  2. Leaves the processing of the data in the parent where the parent form is the “Smart Component” and the child is a “Dumb Component”

Most solutions I was able to find attack this problem assuming the child component will be part of an array of controls.  And I suppose, if you wanted to, you could implement that pattern using an array with one element.  But, that just felt like a hack.  If you are interested in that solution, this is the wrong article.

Attaching an Angular Child Component's Form to a Parent
Photo by loomingy1 on Visual hunt / CC BY

Avoiding the Problem

Up until recently, I’ve been able to avoid this problem entirely by creating separate forms and listening to each individually.  I could have done the same thing here.  But, every time I use this solution, I feel like there must be a better way.  Besides, when you do this correctly, you only need to have one place where you are listening for changes to the form and one place where you send changes into the form.  The work around requires multiples of each.

Basics of Nested Forms

Another way of avoiding the problem is to create the form as one monolithic component.  A very simple implementation would be to have a form that looked something like this:

<form [formGroup]="form">
  <input type="text" formControlName="mainInput">
  <div formGroupName="childGroup">
    <input type="text" formControlName="childInput"
  </div>
</form>

And the reactive definition in the typescript that looked like this:

export class AppComponent {
  form: FormGroup;
  constructor(formBuilder: FormBuilder) {
    this.form = formBuilder.group({
      mainInput: '',
      childGroup: formBuilder.group({
        childInput: ''
      })
    });
  }
}

And then we would grab the data from the valueChanges observable or patch the data into the form using childGroup.childInput.

Creating the Child Component

But what if you we want everything in the childGroup to be a control?  That control would look something like this:

<div [formGroup]="form">
<input type="text" formControlName="childInput">
</div>

and then our TypeScript code looks like a normal formGroup:

  this.form = formBuilder.group({
    childInput: ''
  });

Embedding the Child in the Parent

Now that we have a separate component for our child form, we can use normal directives to add it into our main form.

<form [formGroup]="form">
  <input type="text" formControlName="mainInput">
  <app-child>
  </app-child>
</form>

And our TypeScript code now only needs a reference to mainInput.

constructor(formBuilder: FormBuilder) {
  this.form = formBuilder.group({
    mainInput: ''
  });
}

Connecting the Child to the Parent

The problem is, whenever the childInput element changes, the parent form’s valueChanges observer won’t get notified because the parent form no longer knows about the child form.  And this is where things interesting.

Hooking the child form to the parent form is actually pretty straight forward.  The trick is knowing when in the component life-cycle to run the code.

The first thing to know is that we aren’t going to be able to hookup the child in the parent until after the child component has been created.  This happens after ngOnInit() so we need to find another lifecycle hook to wire everything up in.  It just so happens that ngAfterViewInit() is the perfect place for this.

Second, it might be tempting to hookup everything in the child component during it’s ngOnInit() method.  But this would too tightly couple the child component to the parent.  Something we would like to avoid.

So, the next thing we need to do is that we need to use @ViewChild() to allow the parent to get a hold of the child component, and ultimately the formGroup member variable it will initialize for us.

@ViewChild(ChildComponent) childComponent: ChildComponent;
And now in ngAfterViewInit() we can add the child’s FormGroup as an additional “control” and set the parent FormGroup to the parent control’s FormGroup.
ngAfterViewInit() {
  this.form.addControl('childForm', this.childComponent.form);
  this.childComponent.form.setParent(this.form);
}

And finally, you’ll want to subscribe to valueChanges and your NgRX Store in ngAfterViewInit() after this wire-up code.

How to Really Screw Up an Angular Project

We all know about best practices.  But what does it take to really mess up a project?  Well, for starters, you do EVERYTHING wrong.  You don’t just ignore one or two best practices, you ignore them all.  By evaluating the mess you can get yourself into by ignoring best practices, I think we can all learn better why these recommendations exist.

How to Really Screw Up an Angular Project
Photo on VisualHunt

Continue reading “How to Really Screw Up an Angular Project”

Humpty Dumpty and Programming

I’ve noticed a pattern in the programming world at large both with programmers and with managers.  We define things how we want them to be for our organization and not how they are.  We are like Humpty Dumpty who says, “When I use a word … it means just what I choose it to mean — neither more nor less.”

There are two places where I see this pattern manifesting.  The Agile movement and Design Patterns.

Humpty Dumpty and Programming
Photo by aturkus on Visualhunt / CC BY

Continue reading “Humpty Dumpty and Programming”