A case for extending Angular Forms
Tags: angular, typescript
Published: 2020-09-06 12:06:30

##Intro

I've been developing in Angular since before it even released officially (from version 2.0.0-rc.5 I think) and it sped up development quite a bit. Although it gives developer quite a powerful and fast tool for developing web applications, there are a few shortcomings to it, one of which lies within the FormGroup. 

Note that I'll be talking about use cases in really big and complex projects and therefore problems I discuss may seem a little exaggerated if You're not familiar with what convoluted business requirements may look like.

##The Shortcomings

###No differentiation between user and programmer input

Angular Forms have single method for setting value: `setValue()` which takes value and options. After setting the value, `valueChanges` event is dispatched to notify about the change. 
Normally it's enough, but sometimes we want to know whether the change came from the user (and maybe trigger some rest call) or was applied programmatically (and do NOT trigger the rest call).

###Single state for Invalid/Disabled

The `FormGroup`, `FormControl` and `FormArray` objects store their status in single field named, well, **status**, the only problem being, it doesn't account for some business cases such as:
1. Changing control value programmaticaly when it's disabled
2. Checking validity of disabled control 

Let's imagine that we have two fields dependent on each other. When field #1 changes value, #2 should be disabled or enabled based on some logic. When disabled, #2 should have it's value either cleared or set to some predefined value. In this case we can first setValue and then disable. But what about the case when #1 changes value **again** and #2 should have whole another value ? we need to call
1. `enable()`
2. `setValue()`
3. `disable()`

This is tedious and surely, there should be easier to do this.

###No default value

In order to clear the control value we have to call `reset()` method and pass some value into it. I'd argue that this is not good design. In the [Angular repo](https://github.com/angular/angular/blob/master/packages/forms/src/model.ts) You can read that this method:

```
Resets the form control, marking it `pristine` and `untouched`, and setting the value to null.
```

Well, this all well and nice BUT we have the ability to set control value **when we create it** and that changes a lot. When we pass value at creation, shouldn't `reset()` restore that value ? Of course it should, that's what *reset* means. Current behaviour of this method does not match the name, there should be another method called `clear()` which will work as `reset()` works right now, and `reset()` should restore the initial value.

###Separation from view

Angular forms, although tight to input, have no connection to the view itself which normally is a very good thing. But as usual, there is one case where I think it should be and that's the **visibility** of the input. 

Let's imagine that we have input #1 which decides whether to show input #2 or #3. Right now we can only listen for changes in #1 and then set some variable (ideally only 1) which tells us which other input to show: #2 or #3. Not only that but we also need to clear control value when hiding it and resetting it to some default value when it's shown.

It would be much easier if the `Forms` contained state called `visibility` and methods `get visible()`, `show()` and `hide()`. Those methods could also handle resetting and clearing value of the controller when shown or hidden respectively. 
 
##The Case
And so, we've listed shortcomings - what now ? Do we expect Angular devs to fix these for us ? Do we say to 'no' to business requirements ?

The answer to both questions is **no**. We cannot expect anyone to fix this, because, in their case it may not be broken. They are writing framework for everyone to use, we cannot expect everyone to have the same problems. As to second question - let's be real. Unless it really is undoable in any way, we cannot say no to business requirement. We can point stupid ones, but we cannot say no just because we want to.

##The Solution
There are only two solutions left: 
1. to extend or rewrite the Angular Forms, which is easier than you may think,
2. or use what we have and write bunch of if statements. 

Obviously, I'm going with the first solution and in the near future I'll follow through with article about how I extended Angular Forms and some tips on what I would do differently next time.

##Summary
Hope You enjoyed my thoughts on Angular Forms 😊 If you have another use cases or know the reasons behind Angular devs decisions to write things that way, let me know in comments below 😊

We continue this topic in [part 2](https://dev.to/digitalcrafting/a-case-for-extending-angular-forms-part-2-5268)