Lazy Loading Feature Modules in Angular
ng generate module customers --route customer-list --module app.module
tsconfig.app.json & tsconfig.json
"module": "esnext"
ng generate module customers --route customer-list --module app.module
tsconfig.app.json & tsconfig.json
"module": "esnext"
import { Component, forwardRef, HostBinding, Input } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; @Component({ selector: 'rating-input', template: ` <span *ngFor="let starred of stars; let i = index" (click)="onTouched(); rate(i + (starred ? (value > i + 1 ? 1 : 0) : 1))"> <ng-container *ngIf="starred; else noStar">⭐</ng-container> <ng-template #noStar>·</ng-template> </span> `, styles: [` span { display: inline-block; width: 25px; line-height: 25px; text-align: center; cursor: pointer; } `], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RatingInputComponent), multi: true } ] }) export class RatingInputComponent implements ControlValueAccessor { stars: boolean[] = Array(5).fill(false); // Allow the input to be disabled, and when it is make it somewhat transparent. @Input() disabled = false; @HostBinding('style.opacity') get opacity() { return this.disabled ? 0.25 : 1; } // Function to call when the rating changes. onChange = (rating: number) => {}; // Function to call when the input is touched (when a star is clicked). onTouched = () => {}; get value(): number { return this.stars.reduce((total, starred) => { return total + (starred ? 1 : 0); }, 0); } rate(rating: number) { if (!this.disabled) { this.writeValue(rating); } } // Allows Angular to update the model (rating). // Update the model and changes needed for the view here. writeValue(rating: number): void { this.stars = this.stars.map((_, i) => rating > i); this.onChange(this.value) } // Allows Angular to register a function to call when the model (rating) changes. // Save the function as a property to call later here. registerOnChange(fn: (rating: number) => void): void { this.onChange = fn; } // Allows Angular to register a function to call when the input has been touched. // Save the function as a property to call later here. registerOnTouched(fn: () => void): void { this.onTouched = fn; } // Allows Angular to disable the input. setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; } }
References
https://alligator.io/angular/custom-form-control/
https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
@font-face { font-family: Lato; src: url(/assets/fonts/Lato.woff2) format('woff2'), url(/assets/fonts/Lato.woff) format('woff'); }
h1 { font-family: Lato, sans-serif; }
References
https://alligator.io/css/font-face/
https://stackoverflow.com/questions/49878988/how-to-import-a-new-font-into-a-project-angular-5
As the name suggests, we can add a resolve function to the route which loads the component that has an API call to do. This will cause the component to be only loaded and displayed by Angular once the API call (or whatever else we define) is loaded.
Create a separate class which we’ll have the resolver functionality
// resolver.ts import { Injectable } from '@angular/core'; import { Resolve } from '@angular/router'; import { Observable } from 'rxjs'; import { ApiService } from './api.service'; @Injectable() export class Resolver implements Resolve<Observable<string>> { constructor(private api: ApiService) { } resolve() { return this.api.getProducts(); } }
Add this class as a provider
// app.module.ts import { Resolver } from './resolver'; // ... providers: [Resolver],
app-routing.module.ts
// app-routing.module.ts import { Resolver } from './resolver'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'products', component: ProductsComponent, resolve: { products: Resolver } } ];
// products.component.ts import { ActivatedRoute } from '@angular/router'; // ... constructor(private route: ActivatedRoute) { } products; ngOnInit() { this.products = this.route.snapshot.data.products; }
Access to Route Params
import { Injectable } from '@angular/core'; import { HnService } from './hn.service'; import { Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router'; @Injectable() export class HnResolver implements Resolve<any> { constructor(private hnService: HnService) {} resolve(route: ActivatedRouteSnapshot) { return this.hnService.getPost(route.paramMap.get('id')); } }
References
https://blog.fullstacktraining.com/loading-data-before-components-in-angular/
https://alligator.io/angular/route-resolvers/
rsync -avz -e 'ssh -p 22002' /root/backup/monitoring_201909280430 [email protected]:/root/backup/
Start a new session
tmux tmux new tmux new-session
Start a new session with the name mysession
tmux new -s mysession
kill/delete session mysession
tmux kill-session -t mysession
kill/delete all sessions but the current
tmux kill-session -a
kill/delete all sessions but mysession
tmux kill-session -a -t mysession
Show all sessions
tmux ls tmux list-sessions
Attach to a session with the name mysession
tmux a -t mysession tmux at -t mysession tmux attach -t mysession tmux attach-session -t mysession
Rename session
Ctrl + b $
Detach from session
Ctrl + b d
Create window
Ctrl + b c
Rename current window
Ctrl + b ,
Close current window
Ctrl + b &
Previous window
Ctrl + b p
Next window
Ctrl + b n
Switch/select window by number
Ctrl + b 0 ... 9
Scroll
Ctrl-b [ # Press q to quit scroll mode
Ctrl-b PgUp
References
https://tmuxcheatsheet.com/
https://gist.github.com/MohamedAlaa/2961058
apply plugin: 'groovy' repositories { mavenCentral() } dependencies { compile 'org.codehaus.groovy:groovy-all:2.0.5' } task runScript (dependsOn: 'classes', type: JavaExec) { main = 'myscript' classpath = sourceSets.main.runtimeClasspath }
References
https://stackoverflow.com/questions/17360719/running-groovy-scripts-from-gradle
https://mrhaki.blogspot.com/2014/09/gradle-goodness-running-groovy-scripts.html
private MongoCollection<Document> createCollection(String collectionName) { String indexFieldName1 = "itemId"; String indexFieldName2 = "time"; MongoCollection<Document> mongoCollection = this.database.getCollection(collectionName); if (mongoCollection == null) { this.database.createCollection(collectionName); mongoCollection = this.database.getCollection(collectionName); } IndexOptions indexOptions1 = new IndexOptions().unique(false) .background(false).name(indexFieldName1); Bson keys1 = new Document(indexFieldName1, Integer.valueOf(1)); mongoCollection.createIndex(keys1, indexOptions1); IndexOptions indexOptions2 = new IndexOptions().unique(false) .background(false).name(indexFieldName2); Bson keys2 = new Document(indexFieldName2, Integer.valueOf(1)); mongoCollection.createIndex(keys2, indexOptions2); return mongoCollection; }
yarn upgrade yarn upgrade left-pad yarn upgrade left-pad@^1.0.0 yarn upgrade left-pad grunt yarn upgrade @angular
yarn upgrade --pattern gulp yarn upgrade left-pad --pattern "gulp|grunt" yarn upgrade --latest --pattern "gulp-(match|newer)"
yarn upgrade --latest yarn upgrade left-pad --latest yarn upgrade left-pad grunt --latest --tilde
HTML
<!-- This snippet uses Font Awesome 5 Free as a dependency. You can download it at fontawesome.io! --> <body> <div class="container"> <div class="row"> <div class="col-sm-9 col-md-7 col-lg-5 mx-auto"> <div class="card card-signin my-5"> <div class="card-body"> <h5 class="card-title text-center">Sign In</h5> <form class="form-signin"> <div class="form-label-group"> <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus> <label for="inputEmail">Email address</label> </div> <div class="form-label-group"> <input type="password" id="inputPassword" class="form-control" placeholder="Password" required> <label for="inputPassword">Password</label> </div> <div class="custom-control custom-checkbox mb-3"> <input type="checkbox" class="custom-control-input" id="customCheck1"> <label class="custom-control-label" for="customCheck1">Remember password</label> </div> <button class="btn btn-lg btn-primary btn-block text-uppercase" type="submit">Sign in</button> <hr class="my-4"> <button class="btn btn-lg btn-google btn-block text-uppercase" type="submit"><i class="fab fa-google mr-2"></i> Sign in with Google</button> <button class="btn btn-lg btn-facebook btn-block text-uppercase" type="submit"><i class="fab fa-facebook-f mr-2"></i> Sign in with Facebook</button> </form> </div> </div> </div> </div> </div> </body>
CSS
:root { --input-padding-x: 1.5rem; --input-padding-y: .75rem; } body { background: #007bff; background: linear-gradient(to right, #0062E6, #33AEFF); } .card-signin { border: 0; border-radius: 1rem; box-shadow: 0 0.5rem 1rem 0 rgba(0, 0, 0, 0.1); } .card-signin .card-title { margin-bottom: 2rem; font-weight: 300; font-size: 1.5rem; } .card-signin .card-body { padding: 2rem; } .form-signin { width: 100%; } .form-signin .btn { font-size: 80%; border-radius: 5rem; letter-spacing: .1rem; font-weight: bold; padding: 1rem; transition: all 0.2s; } .form-label-group { position: relative; margin-bottom: 1rem; } .form-label-group input { height: auto; border-radius: 2rem; } .form-label-group>input, .form-label-group>label { padding: var(--input-padding-y) var(--input-padding-x); } .form-label-group>label { position: absolute; top: 0; left: 0; display: block; width: 100%; margin-bottom: 0; /* Override default `<label>` margin */ line-height: 1.5; color: #495057; border: 1px solid transparent; border-radius: .25rem; transition: all .1s ease-in-out; } .form-label-group input::-webkit-input-placeholder { color: transparent; } .form-label-group input:-ms-input-placeholder { color: transparent; } .form-label-group input::-ms-input-placeholder { color: transparent; } .form-label-group input::-moz-placeholder { color: transparent; } .form-label-group input::placeholder { color: transparent; } .form-label-group input:not(:placeholder-shown) { padding-top: calc(var(--input-padding-y) + var(--input-padding-y) * (2 / 3)); padding-bottom: calc(var(--input-padding-y) / 3); } .form-label-group input:not(:placeholder-shown)~label { padding-top: calc(var(--input-padding-y) / 3); padding-bottom: calc(var(--input-padding-y) / 3); font-size: 12px; color: #777; } .btn-google { color: white; background-color: #ea4335; } .btn-facebook { color: white; background-color: #3b5998; } /* Fallback for Edge -------------------------------------------------- */ @supports (-ms-ime-align: auto) { .form-label-group>label { display: none; } .form-label-group input::-ms-input-placeholder { color: #777; } } /* Fallback for IE -------------------------------------------------- */ @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { .form-label-group>label { display: none; } .form-label-group input:-ms-input-placeholder { color: #777; } }
References
https://startbootstrap.com/snippets/login/