A case for extending Angular Forms - part 5
Tags: angular, typescript
Published: 2020-11-18 13:10:57

# Intro
In my [previous article](https://dev.to/digitalcrafting/a-case-for-extending-angular-forms-part-4-1518) we changed the `reset()` methods of angular forms and added `clear()`. This time, we are going to differentiate the user input from the programmer (or code) input.

# The how
We have actually two options to do this, both of them require adding at least one new method which we will call: `setControlValue()` since we will be changing the `FormControl` value:
1. Add another method `setInputValue()` which will signify that the input has changed
2. Use existing `setValue()` as the one for the user input

Since the first option is only viable if you, for some reason, separate *input* from the *forms*, we are going the second path which is also easier to implement.

In the `setControlValue()` we will enable setting the value *even if the control is disabled*, because sometimes it's nice to have. We will also use the `setValue()` method to change the internal value **but** we will not trigger the `valueChanges` event unless programmer wants it. Hope this becomes clearer with the implementation.

# Implementation
Similarly to previous functionality, we first need to declare extra method. We will do that in the `AbstractControl` for compatibility with `formGroup.get()` method, and in the `FormControl` for actual functionality:

``` javascript
declare module "@angular/forms" {
  interface AbstractControl {
    ...
    controlValueChanges: EventEmitter<any>;
    setControlValue(value: any, options?: {emitEvent?: boolean, emitValueEvent?: boolean});      
  }
  interface FormControl extends AbstractControl {
    setControlValue(value: any, options?: {emitEvent?: boolean, emitValueEvent?: boolean});
  }
}
```
In the `AbstractControl` we initialize the `EventEmitter` and just proxy the `setControlValue` arguments to `setValue` for compatibility:

``` javascript
AbstractControl.prototype.controlValueChanges = new EventEmitter<any>();

AbstractControl.prototype.setControlValue = function (value: any, options: { emitEvent?: boolean, emitValueEvent?: boolean }): void {
    let opt = options ? {emitEvent: options.emitValueEvent} : null;
    this.setValue(value, opt);
};
```

And in the `FormControl` we actually implement the desired functionality:

``` javascript
FormControl.prototype.setControlValue = function (value: any, options?: { emitEvent?: boolean, emitValueEvent?: boolean }): void {
    if (this.disabled) {
        this.enable();
        this.setValue(value, {emitEvent: options && options.emitValueEvent});
        this.disable();
    } else {
        this.setValue(value, {emitEvent: options && options.emitValueEvent});
    }
    if (options && options.emitEvent) {
        this.controlValueChanges.emit(value);
    }
};
```

And that's it. We now have an option to override user input even for the disabled control.

# Conclusion
This concludes this series. During just few articles, we have extended the Angular Forms quite a bit. We can show and hide controls from a single place (and also do not consider hidden controls for validation), we can reset the control to default value or clear it completely, we can determine whether the value change came from user input or from our internal logic. And it wasn't even that hard when using `prototype`.

Obviously there might be some corner cases which I forgot about and it needs **a lot** more testing, especially automated, but otherwise, it works. 

Hope this series will be of use to you and that you learned something new along the way :)