hello.component.html
<p>Hello, <span (click)="toggle.emit($event)">{{ world }}</span>!</p>
hello.component.css
p {
color: red;
}
Angular inline component
import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter }
from '@angular/core';
@Component({
selector: 'std-hello',
template: `
<p>Hello, <span (click)="toggle.emit($event)">{{ world }}</span>!</p>
`,
styles: ['p { color: red; }'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HelloComponent {
@Input() world = 'world';
@Output() toggle: EventEmitter<any> = new EventEmitter<any>();
constructor() {}
}
Angular Module
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HelloComponent } from './hello/hello.component';
@NgModule({
declarations: [
HelloComponent,
],
imports: [
CommonModule
],
exports: [
HelloComponent,
]
})
export class HelloModule { }
React Component
HelloComponent.jsx
import React from 'react';
import './HelloComponent.css';
export const HelloComponent = React.memo(
({world, toggle}) => <p>Hello, <span onClick={toggle}>{{world}}</p>
);
HelloComponent.css
p {
color: red;
}
React Component + Typescript
HelloComponent.tsx
import React from 'react';
import './HelloComponent.css';
interface HelloComponentProps {
world: string;
toggle: VoidFunction;
}
export const HelloComponent = React.memo(
({world, toggle}: HelloComponentProps) =>
<p>Hello, <span onClick={toggle}>{{world}}</p>
);
Lit-Element + Typescript
hello.ts
import { LitElement, css, html, property, customElement } from 'lit-element';
@customElement('lit-hello')
export class HelloComponent extends LitElement {
@property() name = 'World';
static get styles() {
return css`
:host {
p {
color: red;
}
}`;
}
render() { return html`<p >Hello, ${this.name}!</p>`; }
}
Typescript Decorator
or: how to hide a function call?
Simple decorator
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
Compiled version...
"use strict";
// Requires `experimentalDecorators` enabled
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
// http://www.typescriptlang.org/docs/handbook/decorators.html
let Greeter = class Greeter {
constructor(message) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
};
Greeter = __decorate([
sealed
], Greeter);
function sealed(constructor) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
Pretty much the same thing
export const Greeter = sealed(class _Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
})
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
Decorator factory
function f() {
console.log("f(): evaluated");
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("f(): called");
}
}
class C {
@f()
method() {}
}
console
f(): evaluated
f(): called
Strings Template Tag
A standard thing to manipulate string
Let's define a tag
function myTag(strings, personExp, ageExp) {
var str0 = strings[0]; // "That "
var str1 = strings[1]; // " is a "
var ageStr;
if (ageExp > 99){
ageStr = 'centenarian';
} else {
ageStr = 'youngster';
}
// We can even return a string built using a template literal
return `${str0}${personExp}${str1}${ageStr}`;
}
Let's use it
var person = 'Mike';
var age = 28;
var output = myTag`That ${ person } is a ${ age }`;
console.log(output);
// That Mike is a youngster
And if we need a tag that do nothing?
export const html = String.raw;
Let's rewrite Angular syntax
import { css, html, StatelessComponent } from 'angular-function-component';
export const HelloComponent = StatelessComponent(
'hello',
['[world]', '(toggle)'],
html`
<p>Hello, <span (click)="toggle.emit($event)">{{world}}</span>!</p>
`,
css`
p {
color: red;
}
`,
);
import { css, html, StatelessComponent } from 'angular-function-component';
export const HelloComponent = StatelessComponent({
selector: 'my-comp',
inputs: ['world'],
outputs: ['toggle'],
template:
html`<p>Hello, <span (click)="onWhoClick.emit($event)">{{who}}</span>!</p>`,
style: css`p {color: red;}`,
});
Stateless Component in the future
-
It will works as long as Angular will use Typescript Decorator
-
No idea if it will works with ES7 Decorators (Stage 2)
-
Soon Ivy will let us to declare dependencies from components directly
import { Component } from '@angular/core';
import { MatButton, MatIcon } from '@angular/material';
@Component({
+ deps: [ MatButton, MatIcon, ],
selector: 'cart-button',
template: `
<button mat-icon-button type="button" (click)="onClick()">
<mat-icon aria-label="Add to shopping cart">shopping_cart</mat-icon>
</button>
`,
})
export class CartButtonComponent {
onClick(): void { this.addToShoppingCart(); }
private addToShoppingCart(): void {}
}