Check Theme of Browser
Theme of the browser
const theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light",
const theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light",
An improvement would be to extract the event listener callback function in order to remove the listener when the component unmounts.
import React from 'react';
import 'road-dropdown';
const Dropdown = ({ label, option, options, onChange }) => {
const ref = React.useRef();
React.useLayoutEffect(() => {
const handleChange = customEvent => onChange(customEvent.detail);
const { current } = ref;
current.addEventListener('onChange', handleChange);
// returning the callback in order to remove the listener when the component unmounts.
return () => current.removeEventListener('onChange', handleChange);
}, [ref]);
return (
<road-dropdown
ref={ref}
label={label}
option={option}
options={JSON.stringify(options)}
/>
);
};
That's it for adding an event listener for
Below works with the useCustomElement React Hook which can be installed via npm install use-custom-element:
import React from 'react';
import 'road-dropdown';
import useCustomElement from 'use-custom-element';
const Dropdown = props => {
const [customElementProps, ref] = useCustomElement(props);
return <road-dropdown {...customElementProps} ref={ref} />;
};
The HTMLSlotElement interface of the Shadow DOM API enables access to the name and assigned nodes of an HTML <slot> element.
Special callback functions defined inside the custom element's class definition, which affect its behavior:
connectedcallback
Invoked when the custom element is first connected to the document's DOM.
disconnectedcallback
Invoked when the custom element is disconnected from the document's DOM.
adoptedcallback
Invoked when the custom element is moved to a new document.
attributechangedcallback
Invoked when one of the custom element's attributes is added, removed, or changed.
:defined {}
:host {}
:host() {}
:host-context() {}
<wc-parent>
<wc-child>
<wc-subchild>
</wc-subchild>
</wc-child>
<wc-parent>
function findParent(startElement: Element | ShadowRoot, selector: string): Element | null {
let result: Element | null;
if (startElement instanceof HTMLElement) {
result = startElement.closest(selector);
if (result) {
return result;
}
}
const r = startElement.getRootNode();
if (r instanceof ShadowRoot) {
return findParent((r as ShadowRoot).host, selector);
}
return null;
}
// wc-subchild component
findParent(this.shadowRoot, 'wc-parent');
Unlike providers of the modules loaded at launch, providers of lazy-loaded modules are module-scoped.
When the Angular router lazy-loads a module, it creates a new execution context. That context has its own injector, which is a direct child of the application injector.
The router adds the lazy module's providers and the providers of its imported NgModules to this child injector.
These providers are insulated from changes to application providers with the same lookup token. When the router creates a component within the lazy-loaded context, Angular prefers service instances created from these providers to the service instances of the application root injector.
'-' or '------': Equivalent to [NEVER](<https://rxjs.dev/api/index/const/NEVER>), or an observable that never emits or errors or completes.
|: Equivalent to [EMPTY](<https://rxjs.dev/api/index/const/EMPTY>), or an observable that never emits and completes immediately.
#: Equivalent to [throwError](<https://rxjs.dev/api/index/function/throwError>), or an observable that never emits and errors immediately.
'--a--': An observable that waits 2 "frames", emits value a on frame 2 and then never completes.
'--a--b--|': On frame 2 emit a, on frame 5 emit b, and on frame 8, complete.
'--a--b--#': On frame 2 emit a, on frame 5 emit b, and on frame 8, error.
'-a-^-b--|': In a hot observable, on frame -2 emit a, then on frame 2 emit b, and on frame 5, complete.
'--(abc)-|': on frame 2 emit a, b, and c, then on frame 8, complete.
'-----(a|)': on frame 5 emit a and complete.
'a 9ms b 9s c|': on frame 0 emit a, on frame 10 emit b, on frame 9,011 emit c, then on frame 9,012 complete.
'--a 2.5m b': on frame 2 emit a, on frame 150,003 emit b and never complete.
import { TestScheduler } from 'rxjs/testing';
import { throttleTime } from 'rxjs';
const testScheduler = new TestScheduler((actual, expected) => {
// asserting the two objects are equal - required
// for TestScheduler assertions to work via your test framework
// e.g. using chai.
expect(actual).deep.equal(expected);
});
// This test runs synchronously.
it('generates the stream correctly', () => {
testScheduler.run((helpers) => {
const { cold, time, expectObservable, expectSubscriptions } = helpers;
const e1 = cold(' -a--b--c---|');
const e1subs = ' ^----------!';
const t = time(' ---| '); // t = 3
const expected = '-a-----c---|';
expectObservable(e1.pipe(throttleTime(t))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
testScheduler.run((helpers) => {
const { time, cold } = helpers;
const source = cold('---a--b--|');
const t = time(' --| ');
// --|
const expected = ' -----a--b|';
const result = source.pipe(delay(t));
expectObservable(result).toBe(expected);
});
testScheduler.run((helpers) => {
const { animate, cold } = helpers;
animate(' ---x---x---x---x');
const requests = cold('-r-------r------');
/* ... */
const expected = ' ---a-------b----';
});
});
import { HttpErrorResponse } from '@angular/common/http';
import { ErrorHandler, Injectable, NgZone } from '@angular/core';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
constructor() {}
public handleError(error: any): void {
// Check if it's an error from an HTTP response
const isServerError = error instanceof HttpErrorResponse;
if (!isServerError) {
// TODO
}
console.error('Error from Global Error Handler', error);
}
}
@NgModule({
declarations: [AppComponent],
imports: [
CommonModule,
HttpClientModule,
],
providers: [
{ provide: ErrorHandler, useClass: GlobalErrorHandler },
],
bootstrap: [AppComponent],
})
export class AppModule {}
// Get the injector
var injector = angular.element($0/*'[data-ng-app], [ng-app]'*/).injector();
// Get the service
var service = injector.get('Service');
https://angular.io/guide/lazy-loading-ngmodules#preloading-modules
import { PreloadAllModules } from '@angular/router';
RouterModule.forRoot(
appRoutes,
{
preloadingStrategy: PreloadAllModules
}
)
import { Resolve } from '@angular/router';
...
/* An interface that represents your data model */
export interface Crisis {
id: number;
name: string;
}
export class CrisisDetailResolverService implements Resolve {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {
// your logic goes here
}
}
import { CrisisDetailResolverService } from './crisis-detail-resolver.service';
{
path: '/your-path',
component: YourComponent,
resolve: {
crisis: CrisisDetailResolverService
}
}
import { ActivatedRoute } from '@angular/router';
@Component({ ... })
class YourComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.data
.subscribe(data => {
const crisis: Crisis = data.crisis;
// ...
});
}
}
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {CustomPreloadingStrategyService} from './custom-preloading-strategy.service';
const routes: Routes = [
{path: 'about', data: {preload: true}, loadChildren: () => import('./about/about.module').then(m => m.AboutModule)},
{path: 'users', loadChildren: () => import('./users/users.module').then(m => m.UsersModule)},
{path: '', redirectTo: '', pathMatch: 'full'}
];
@NgModule({
imports: [RouterModule.forRoot(routes, {preloadingStrategy: CustomPreloadingStrategyService})],
exports: [RouterModule]
})
export class AppRoutingModule {
}
import {Injectable} from '@angular/core';
import {PreloadingStrategy, Route} from '@angular/router';
import {Observable, of} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CustomPreloadingStrategyService implements PreloadingStrategy {
preload(route: Route, fn: () => Observable<any>): Observable<any> {
if (route.data && route.data.preload) {
return fn(); // Proceeds with preloading
}
return of(null); // Proceeds without preloading
}
}
import {HttpTestingController} from '@angular/common/http/testing';
describe('DataService', () => {
let service: DataService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule],
providers: [DataService]
});
service = TestBed.get(DataService);
httpMock = TestBed.get(HttpTestingController);
});
afterEach(() => {
httpMock.verify();
});
it('be able to retrieve posts from the API bia GET', () => {
const dummyPosts: Post[] = [{
userId: '1',
id: 1,
body: 'Hello World',
title: 'testing Angular'
}, {
userId: '2',
id: 2,
body: 'Hello World2',
title: 'testing Angular2'
}];
service.getPost().subscribe(posts => {
expect(posts.length).toBe(2);
expect(posts).toEqual(dummyPosts);
});
const request = httpMock.expectOne( `${service.ROOT_URl}/posts`);
expect(request.request.method).toBe('GET');
request.flush(dummyPosts);
});
});