I am trying to add functionality to the built-in NgForm
directive by intercepting the onSubmit
function in order to prevent double-submission and invalid submission, but I haven't been able to find a way to do so without monkey patching.
I didn't really expect this to work with directives since they aren't really "providers", but I tried it anyway (to no avail).
import { Injectable } from '@angular/core';
import { NgForm } from '@angular/forms';
@Injectable()
export class NgFormDecorator extends NgForm {
constructor() {
super(null, null);
}
onSubmit($event: Event): boolean {
// TODO: Prevent submission if in progress
return super.onSubmit($event);
}
}
// Module configuration
providers: [{
provide: NgForm,
useClass: NgFormDecorator
}]
This works great but is obviously not ideal.
import { Directive, Output, EventEmitter } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/finally';
import { noop } from 'rxjs/util/noop';
@Directive({
selector: 'form',
exportAs: 'NgFormExtension'
})
export class NgFormExtensionDirective {
private onSubmitBase: ($event: Event) => void;
submitting: boolean;
constructor(private ngForm: NgForm) {
this.onSubmitBase = ngForm.onSubmit;
ngForm.onSubmit = this.onSubmit.bind(this);
}
private onSubmit($event: FormSubmitEvent): boolean {
if (this.submitting || this.ngForm.invalid) {
return false;
}
this.submitting = true;
const result = this.onSubmitBase.call(this.ngForm, $event);
if ($event.submission) {
$event.submission
.finally(() => this.submitting = false)
.subscribe(null, noop);
} else {
this.submitting = false;
}
return result;
}
}
export class FormSubmitEvent extends Event {
submission: Observable<any>;
}
Is there a way to decorate/intercept a built-in directive in Angular 4 without monkey patching?
The Component is used to break up the application into smaller components. That is why components are widely used in later versions of Angular to make things easy and build a total component-based model. The Directive is used to design reusable components, which are more behavior-oriented.
Components are directives with templates. The only difference between Components and the other two types of directives is the Template. Attribute and Structural Directives don't have Templates. So, we can say that the Component is a cleaner version of the Directive with a template, which is easier to use.
The asterisk is "syntactic sugar". It simplifies ngIf and ngFor for both the writer and the reader. Under the hood, Angular replaces the asterisk version with a more verbose form. The next two ngIf examples are effectively the same and we may write in either style: <!--
The three types of directives in Angular are attribute directives, structural directives, and components.
You can always just override the ngForm
selector, and extend the NgForm
class:
@Directive({
selector: 'form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]',
})
export class CNgFormDirective extends NgForm {
constructor(
@Optional() @Self() @Inject(NG_VALIDATORS) validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: any[]) {
super(validators, asyncValidators);
}
onSubmit($event: Event): boolean {
console.log(`I'm custom!`);
return super.onSubmit($event);
}
}
working stack
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With