IntelliJ IDE Live Templates
Posted on Fri 01 January 2021 in Development • 2 min read
Writing the same boilerplate code over-and-over again isn't an experience that I frequently have when writing Python code, but as I often work with Angular code.. which is frustrating and mind-numbing.
For an example--let's take an extremely standard angular component, which is using the reactive forms library.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import { OnInit, Component } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { AuthService } from './auth.service'; @Component({ selector: 'my-login', template: ` <h1>Login</h1> <form [formGroup]="form" (ngSubmit)="login()"> <mat-form-field> <input matInput placeholder="Username" [formControl]="username"> <mat-error *ngIf="username.hasError('required')">Username is <strong>required</strong></mat-error> </mat-form-field> <mat-form-field> <input matInput placeholder="Password" [formControl]="password" type="password"> <mat-error *ngIf="password.hasError('required')">Password is <strong>required</strong></mat-error> </mat-form-field> <div> <button mat-raised-button color="primary" type="submit" [disabled]="!this.form.valid">Login</button> </div> </form> `, styles: [ ] }) export class LoginComponent implements OnInit { form!: FormGroup; constructor(protected fb: FormBuilder, protected service: AuthService) { } ngOnInit(): void { this.form = this.fb.group({ username: ['', [Validators.required, ]], password: ['', [Validators.required, ]], }); } get username(): FormControl { return this.form.get('username') as FormControl; } get password(): FormControl { return this.form.get('password') as FormControl; } login(): void { this.isBusy = true; this.service.login(this.username.value, this.password.value).subscribe( () => alert('mantul bos'), (error) => alert('waduh masbro!') ); } } |
The way, recommended in the Angular documentation to reference FormControls (as FormGroups don't support generics.. and therefore aren't pseudo "strongly-typed"), is to return them from property getters, as referenced above.
The above example only has 2 inputs, but given applications such as admin panels are likely to have hundreds of inputs throughout the whole app, constantly writing..
get ???(): FormControl { return this.form.get('???') as FormControl; }
..Is tedious.
Let's fix that:
Preferences > Live Templates
There are already many "live templates" included in PyCharm, however not one exactly for our needs. In order to make things simple, we're going to follow IntelliJ's naming conventions, and we're going to use 'a-' ... and since we're going to be making a 'property getter' for a 'FormControl' we're going to call our snippet (live template) 'a-fcgetter'.
(Rant... I find the name live templates confusing; I'm embarassed to say how much time I spent working with PyCharm before I realized this feature existed because coming from Visual Studio I would've expected)