Reactivity
Declare state
React
import { useState } from 'react';
export default function Name() {
const [name] = useState('John');
return <h1>Hello {name}</h1>;
}
<script setup>
import { ref } from 'vue';
const name = ref('John');
</script>
<template>
<h1>Hello {{ name }}</h1>
</template>
Angular
import { Component } from '@angular/core';
@Component({
selector: 'app-name',
template: '<h1>Hello {{ name }}</h1>',
})
export class NameComponent {
name: string = 'John';
}
import { createSignal } from 'solid-js';
export default function Name() {
const [name] = createSignal('John');
return <h1>Hello {name()}</h1>;
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./name.js"></script>
</head>
<body>
<x-name></x-name>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
@customElement('x-name')
export class XName extends LitElement {
@state()
name = 'John';
render() {
return html`<h1>Hello ${this.name}!</h1>`;
}
}
Ember
<h1>Hello {{this.name}}</h1>
import Component from '@glimmer/component';
export default class CounterComponent extends Component {
name = 'John';
}
Qwik
import { component$, useStore } from '@builder.io/qwik';
export const Name = component$(() => {
const store = useStore({ name: 'John' });
return <h1>Hello {store.name}</h1>;
});
Update state
React
import { useState } from 'react';
export default function Name() {
const [name, setName] = useState('John');
setName('Jane');
return <h1>Hello {name}</h1>;
}
<script setup>
import { ref } from 'vue';
const name = ref('John');
name.value = 'Jane';
</script>
<template>
<h1>Hello {{ name }}</h1>
</template>
Angular
import { Component } from '@angular/core';
@Component({
selector: 'app-name',
template: '<h1>Hello {{ name }}</h1>',
})
export class NameComponent {
name: string = 'John';
constructor() {
this.name = 'Jane';
}
}
import { createSignal } from 'solid-js';
export default function Name() {
const [name, setName] = createSignal('John');
setName('Jane');
return <h1>Hello {name()}</h1>;
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./name.js"></script>
</head>
<body>
<x-name></x-name>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
@customElement('x-name')
export class XName extends LitElement {
@state()
name = 'John';
constructor() {
super();
this.name = 'Jane';
}
render() {
return html`<h1>Hello ${this.name}!</h1>`;
}
}
Ember
<h1>Hello {{this.name}}</h1>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
export default class CounterComponent extends Component {
@tracked name = 'John';
constructor(owner, args) {
super(owner, args);
this.name = 'Jane';
}
}
Qwik
Missing snippet
Help us to improve Component Party 🎉
Computed state
React
import { useState, useMemo } from 'react';
export default function DoubleCount() {
const [count] = useState(10);
const doubleCount = useMemo(() => count * 2, [count]);
return <div>{doubleCount}</div>;
}
<script setup>
import { ref, computed } from 'vue';
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
</script>
<template>
<div>{{ doubleCount }}</div>
</template>
Angular
import { Component, Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'double',
})
export class DoubleCountPipe implements PipeTransform {
transform(value: number): number {
return value * 2;
}
}
@Component({
selector: 'app-doublecount',
template: '<div>{{ number | double }}</div>',
})
export class DoublecountComponent {
count: number = 10;
}
import { createSignal } from 'solid-js';
export default function DoubleCount() {
const [count] = createSignal(10);
const doubleCount = () => count() * 2;
return <div>{doubleCount()}</div>;
}
Lit
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
@customElement('double-count')
export class DoubleCount extends LitElement {
@state()
count = 10;
get doubleCount() {
return this.count * 2;
}
render() {
return html`<div>${this.doubleCount}</div>`;
}
}
<!DOCTYPE html>
<head>
<script type="module" src="./double-count.js"></script>
</head>
<body>
<double-count></double-count>
</body>
Ember
<div>{{this.doubleCount}}</div>
import Component, { tracked } from '@glimmer/component';
export default class DoubleCount extends Component {
@tracked count = 10;
get doubleCount() {
return this.count * 2;
}
}
<h1
x-data="{
count : 10,
get doubleCount() { return this.count * 2 }
}"
x-text="doubleCount"
></h1>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Templating
Minimal template
React
export default function HelloWorld() {
return <h1>Hello world</h1>;
}
Angular
import { Component } from '@angular/core';
@Component({
selector: 'app-helloworld',
template: '<h1>Hello world</h1>',
})
export class HelloworldComponent {}
Lit
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('hello-world')
export class HelloWorld extends LitElement {
render() {
return html`<h1>Hello world</h1>`;
}
}
<!DOCTYPE html>
<head>
<script type="module" src="./hello-world.js"></script>
</head>
<body>
<hello-world></hello-world>
</body>
Ember
<h1>Hello world</h1>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Styling
<h1 class="title">I am red</h1>
<button style="font-size: 10rem;">I am a button</button>
<style>
.title {
color: red;
}
</style>
React
import './style.css';
export default function CssStyle() {
return (
<>
<h1 className="title">I am red</h1>
<button style={{ 'font-size': '10rem' }}>I am a button</button>
</>
);
}
.title {
color: red;
}
<template>
<h1 class="title">
I am red
</h1>
<button style="font-size: 10rem">
I am a button
</button>
</template>
<style scoped>
.title {
color: red;
}
</style>
Angular
.title {
color: red;
}
<h1 class="title">I am red</h1>
<button style="font-size: 10rem">I am a button</button>
import { Component } from '@angular/core';
@Component({
selector: 'app-cssstyle',
templateUrl: './cssstyle.component.html',
styleUrls: ['./cssstyle.component.css'],
})
export class HelloworldComponent {}
import './style.css';
export default function CssStyle() {
return (
<>
<h1 class="title">I am red</h1>
<button style={{ 'font-size': '10rem' }}>I am a button</button>
</>
);
}
.title {
color: red;
}
Lit
import { LitElement, html, css } from 'lit';
import { customElement } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
@customElement('css-style')
export class CssStyle extends LitElement {
static styles = css`
.title {
color: red;
}
`;
render() {
return html`
<h1 class="title">I am red</h1>
<button style=${styleMap({ fontSize: '10rem' })}>I am a button</button>
`;
}
}
<!DOCTYPE html>
<head>
<script type="module" src="./css-style.js"></script>
</head>
<body>
<css-style></css-style>
</body>
Ember
/* using: https://github.com/salsify/ember-css-modules */
.title {
color: red;
}
<h1 class='title'>I am red</h1>
<button style='font-size: 10rem;'>I am a button</button>
<h1 class="title">I am red</h1>
<button style="font-size: 10rem">I am a button</button>
<style>
.title {
color: red;
}
</style>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Loop
<script>
const colors = ['red', 'green', 'blue'];
</script>
<ul>
{#each colors as color}
<li>{color}</li>
{/each}
</ul>
React
export default function Colors() {
const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li key={color}>{color}</li>
))}
</ul>
);
}
<script setup>
const colors = ['red', 'green', 'blue'];
</script>
<template>
<ul>
<li
v-for="color in colors"
:key="color"
>
{{ color }}
</li>
</ul>
</template>
Angular
<ul>
<li *ngFor="let color of colors">{{ color }}</li>
</ul>
import { Component } from '@angular/core';
@Component({
selector: 'app-colors',
templateUrl: './colors.component.html',
})
export class ColorsComponent {
colors: string[] = ['red', 'green', 'blue'];
}
import { For } from 'solid-js';
export default function Colors() {
const colors = ['red', 'green', 'blue'];
return (
<ul>
<For each={colors}>{(color) => <li>{color}</li>}</For>
</ul>
);
}
Lit
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('colors-list')
export class ColorsList extends LitElement {
colors = ['red', 'green', 'blue'];
render() {
return html`
<ul>
${this.colors.map((color) => html`<li>${color}</li>`)}
</ul>
`;
}
}
<!DOCTYPE html>
<head>
<script type="module" src="./colors-list.js"></script>
</head>
<body>
<colors-list></colors-list>
</body>
Ember
<ul>
{{#each (array 'red' 'green' 'blue') as |color|}}
<li>{{color}}</li>
{{/each}}
</ul>
<ul x-data="{ colors: ['red', 'green', 'blue'] }">
<template x-for="color in colors">
<li x-text="color"></li>
</template>
</ul>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Event click
<script>
let count = 0;
function incrementCount() {
count++;
}
</script>
<p>Counter: {count}</p>
<button on:click={incrementCount}>+1</button>
React
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
function incrementCount() {
setCount((count) => count + 1);
}
return (
<>
<p>Counter: {count}</p>
<button onClick={incrementCount}>+1</button>
</>
);
}
<script setup>
import { ref } from 'vue';
const count = ref(0);
function incrementCount() {
count.value++;
}
</script>
<template>
<p>Counter: {{ count }}</p>
<button @click="incrementCount">
+1
</button>
</template>
Angular
<p>Counter: {{ count }}</p>
<button (click)="incrementCount()">+1</button>
import { Component } from '@angular/core';
@Component({
selector: 'app-counter',
templateUrl: './counter.component.html',
})
export class CounterComponent {
count: number = 0;
incrementCount(): void {
this.count++;
}
}
import { createSignal } from 'solid-js';
export default function Counter() {
const [count, setCount] = createSignal(0);
function incrementCount() {
setCount(count() + 1);
}
return (
<>
<p>Counter: {count()}</p>
<button onClick={incrementCount}>+1</button>
</>
);
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./x-counter.js"></script>
</head>
<body>
<x-counter></x-counter>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
@customElement('x-counter')
export class XCounter extends LitElement {
@state()
count = 0;
incrementCount() {
this.count = this.count + 1;
}
render() {
return html`
<p>Counter: ${this.count}</p>
<button @click=${this.incrementCount}>+1</button>
`;
}
}
Ember
<p>Counter: {{this.count}}</p>
<button {{on 'click' this.incrementCount}}>+1</button>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
export default class Counter extends Component {
@tracked count = 0;
incrementCount = () => this.count++;
}
<div x-data="{ count: 0 }">
<p>Counter: <span x-text="count"></span></p>
<button x-on:click="count++">+1</button>
</div>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Dom ref
<script>
import { onMount } from 'svelte';
let inputElement;
onMount(() => {
inputElement.focus();
});
</script>
<input bind:this={inputElement} />
React
import { useEffect, useRef } from 'react';
export default function InputFocused() {
const inputElement = useRef(null);
useEffect(() => inputElement.current.focus(), []);
return <input type="text" ref={inputElement} />;
}
<script setup>
import { ref, onMounted } from 'vue';
const inputElement = ref();
onMounted(() => {
inputElement.value.focus();
});
</script>
<template>
<input ref="inputElement">
</template>
Angular
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-inputfocused',
template: '<input type="text" #inputelement />',
})
export class InputfocusedComponent implements AfterViewInit {
@ViewChild('inputelement')
inputElement: ElementRef<HTMLInputElement> | undefined;
ngAfterViewInit(): void {
this.inputElement?.nativeElement.focus();
}
}
import { onMount } from 'solid-js';
export default function InputFocused() {
let inputElement;
onMount(() => inputElement.focus());
return <input ref={inputElement} type="text" />;
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./input-focused.js"></script>
</head>
<body>
<input-focused></input-focused>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { ref, createRef } from 'lit/directives/ref.js';
@customElement('input-focused')
export class InputFocused extends LitElement {
inputRef = createRef();
firstUpdated() {
this.inputRef.value.focus();
}
render() {
return html`<input type="text" ${ref(this.inputRef)} />`;
}
}
Ember
<input {{this.autofocus}} />
import Component from '@glimmer/component';
import { modifier } from 'ember-modifier';
export default class InputFocused extends Component {
autofocus = modifier((element) => element.focus());
}
/**
* modifier: https://github.com/ember-modifier/ember-modifier
*
* See also:
* - https://github.com/emberjs/rfcs/pull/811
* - ember-modifier becomes default part of blueprint
* - https://github.com/emberjs/rfcs/pull/757
* - dependencyless support for using
* `autofocus = element => element.focus()`
* instead
*/
Qwik
Missing snippet
Help us to improve Component Party 🎉
Conditional
<script>
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
let lightIndex = 0;
$: light = TRAFFIC_LIGHTS[lightIndex];
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex = 0;
} else {
lightIndex++;
}
}
</script>
<button on:click={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{#if light === 'red'}
<span>STOP</span>
{:else if light === 'orange'}
<span>SLOW DOWN</span>
{:else if light === 'green'}
<span>GO</span>
{/if}
</p>
React
import { useState } from 'react';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
export default function TrafficLight() {
const [lightIndex, setLightIndex] = useState(0);
const light = TRAFFIC_LIGHTS[lightIndex];
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
setLightIndex(0);
} else {
setLightIndex(lightIndex + 1);
}
}
return (
<>
<button onClick={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{light === 'red' && <span>STOP</span>}
{light === 'orange' && <span>SLOW DOWN</span>}
{light === 'green' && <span>GO</span>}
</p>
</>
);
}
<script setup>
import { ref, computed } from 'vue';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
const lightIndex = ref(0);
const light = computed(() => TRAFFIC_LIGHTS[lightIndex.value]);
function nextLight() {
if (lightIndex.value + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex.value = 0;
} else {
lightIndex.value++;
}
}
</script>
<template>
<button @click="nextLight">
Next light
</button>
<p>Light is: {{ light }}</p>
<p>
You must
<span v-if="light === 'red'">STOP</span>
<span v-else-if="light === 'orange'">SLOW DOWN</span>
<span v-else-if="light === 'green'">GO</span>
</p>
</template>
Angular
<button (click)="nextLight()">Next light</button>
<p>Light is: {{ lightIndex | light }}</p>
<p>
You must
<span *ngIf="(lightIndex | light) === 'red'">STOP</span>
<span *ngIf="(lightIndex | light) === 'orange'">SLOW DOWN</span>
<span *ngIf="(lightIndex | light) === 'green'">GO</span>
</p>
import { Component, Pipe, PipeTransform } from '@angular/core';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
@Pipe({
name: 'light',
})
export class TrafficLightPipe implements PipeTransform {
transform(value: number): string {
return TRAFFIC_LIGHTS[value];
}
}
@Component({
selector: 'app-trafficlight',
templateUrl: './trafficlight.component.html',
})
export class TrafficlightComponent {
lightIndex: number = 0;
nextLight(): void {
if (this.lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
this.lightIndex = 0;
} else {
this.lightIndex++;
}
}
}
import { Switch, Match } from 'solid-js/web';
import { createSignal } from 'solid-js';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
export default function TrafficLight() {
const [lightIndex, setLightIndex] = createSignal(0);
const light = () => TRAFFIC_LIGHTS[lightIndex()];
function nextLight() {
if (lightIndex() + 1 > TRAFFIC_LIGHTS.length - 1) {
setLightIndex(0);
} else {
setLightIndex(lightIndex() + 1);
}
}
return (
<>
<button onClick={nextLight}>Next light</button>
<p>Light is: {light()}</p>
<p>
You must
<Switch>
<Match when={light() === 'red'}>
<span>STOP</span>
</Match>
<Match when={light() === 'orange'}>
<span>SLOW DOWN</span>
</Match>
<Match when={light() === 'green'}>
<span>GO</span>
</Match>
</Switch>
</p>
</>
);
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./traffic-light.js"></script>
</head>
<body>
<traffic-light></traffic-light>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { choose } from 'lit/directives/choose.js';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
@customElement('traffic-light')
export class TrafficLight extends LitElement {
@state()
lightIndex = 0;
get light() {
return TRAFFIC_LIGHTS[this.lightIndex];
}
nextLight() {
if (this.lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
this.lightIndex = 0;
} else {
this.lightIndex = this.lightIndex + 1;
}
}
render() {
return html`
<button @click=${this.nextLight}>Next light</button>
<p>Light is ${this.light}</p>
<p>
You must
${choose(this.light, [
['red', () => html`<span>STOP</span>`],
['orange', () => html`<span>SLOW DOWN</span>`],
['green', () => html`<span>GO</span>`],
])}
</p>
`;
}
}
Ember
<button {{on 'click' this.nextLight}}>Next light</button>
<p>Light is: {{this.light}}</p>
<p>
You must
{{#if (eq this.light 'red')}}
STOP
{{else if (eq this.light 'orange')}}
SLOW DOWN
{{else if (eq this.light 'green')}}
GO
{{/if}}
</p>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
export default class TrafficLight extends Component {
@tracked lightIndex = 0;
get light() {
return TRAFFIC_LIGHTS[this.lightIndex];
}
nextLight = () => {
if (this.lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
this.lightIndex = 0;
} else {
this.lightIndex++;
}
};
}
<div
x-data="{
TRAFFIC_LIGHTS: ['red', 'orange', 'green'],
lightIndex: 0,
get light() { return this.TRAFFIC_LIGHTS[this.lightIndex] },
nextLight() {
if (this.lightIndex + 1 > this.TRAFFIC_LIGHTS.length - 1) {
this.lightIndex = 0
} else {
this.lightIndex++
}
}
}"
>
<button x-on:click="nextLight">Next light</button>
<p>Light is: <span x-text="light"></span></p>
<p>
You must
<span x-show="light === 'red'">STOP</span>
<span x-show="light === 'orange'">SLOW DOWN</span>
<span x-show="light === 'green'">GO</span>
</p>
</div>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Lifecycle
On mount
<script>
import { onMount } from 'svelte';
let pageTitle = '';
onMount(() => {
pageTitle = document.title;
});
</script>
<p>Page title is: {pageTitle}</p>
React
import { useState, useEffect } from 'react';
export default function PageTitle() {
const [pageTitle, setPageTitle] = useState('');
useEffect(() => {
setPageTitle(document.title);
}, []);
return <p>Page title: {pageTitle}</p>;
}
<script setup>
import { ref, onMounted } from 'vue';
const pageTitle = ref('');
onMounted(() => {
pageTitle.value = document.title;
});
</script>
<template>
<p>Page title: {{ pageTitle }}</p>
</template>
Angular
import { Component, AfterContentInit } from '@angular/core';
@Component({
selector: 'app-pagetitle',
template: '<p>Page title: {{ pageTitle }}</p>',
})
export class PagetitleComponent implements AfterContentInit {
pageTitle: string = '';
ngAfterContentInit(): void {
this.pageTitle = document.title;
}
}
import { createSignal, onMount } from 'solid-js';
export default function PageTitle() {
const [pageTitle, setPageTitle] = createSignal('');
onMount(() => {
setPageTitle(document.title);
});
return <p>Page title: {pageTitle()}</p>;
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./page-title.js"></script>
</head>
<body>
<page-title></page-title>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
@customElement('page-title')
export class PageTitle extends LitElement {
@state()
pageTitle = '';
connectedCallback() {
super.connectedCallback();
this.pageTitle = document.title;
}
render() {
return html`<p>Page title: ${this.pageTitle}</p>`;
}
}
Ember
<p>Page title is: {{(this.pageTitle)}}</p>
import Component from '@glimmer/component';
export default class PageTitle extends Component {
pageTitle = () => document.title;
}
<p x-data="{ pageTitle: '' }" x-init="$nextTick(() => { pageTitle = document.title })">Page title: <span x-text="pageTitle"></span></p>
Qwik
Missing snippet
Help us to improve Component Party 🎉
On unmount
<script>
import { onDestroy } from 'svelte';
let time = new Date().toLocaleTimeString();
const timer = setInterval(() => {
time = new Date().toLocaleTimeString();
}, 1000);
onDestroy(() => {
clearInterval(timer);
});
</script>
<p>Current time: {time}</p>
React
import { useState, useEffect } from 'react';
export default function Time() {
const [time, setTime] = useState(new Date().toLocaleTimeString());
useEffect(() => {
const timer = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return <p>Current time: {time}</p>;
}
<script setup>
import { ref, onUnmounted } from 'vue';
const time = ref(new Date().toLocaleTimeString());
const timer = setInterval(() => {
time.value = new Date().toLocaleTimeString();
}, 1000);
onUnmounted(() => {
clearInterval(timer);
});
</script>
<template>
<p>Current time: {time}</p>
</template>
Angular
import { Component, OnDestroy } from '@angular/core';
@Component({
selector: 'app-time',
template: '<p>Current time: {{ time }}</p>',
})
export class TimeComponent implements OnDestroy {
time: string = new Date().toLocaleTimeString();
timer: number;
constructor() {
this.timer = window.setInterval(() => {
this.time = new Date().toLocaleTimeString();
}, 1000);
}
ngOnDestroy(): void {
window.clearInterval(this.timer);
}
}
import { createSignal, onCleanup } from 'solid-js';
export default function Time() {
const [time, setTime] = createSignal(new Date().toLocaleTimeString());
const timer = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
onCleanup(() => clearInterval(timer));
return <p>Current time: {time()}</p>;
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./x-time.js"></script>
</head>
<body>
<x-time></x-time>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
@customElement('x-time')
export class XTime extends LitElement {
@state()
time = '';
timer;
connectedCallback() {
super.connectedCallback();
this.timer = setInterval(() => {
this.time = new Date().toLocaleTimeString();
}, 1000);
}
disconnectedCallback() {
super.disconnectedCallback();
clearInterval(this.timer);
}
render() {
return html`<p>Current time: ${this.time}</p>`;
}
}
Ember
<p>Current time: {{this.time}}</p>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { registerDestructor } from '@ember/destroyable';
export default class Time extends Component {
@tracked time = new Date().toLocaleTimeString();
constructor(owner, args) {
super(owner, args);
let timer = setInterval(() => {
this.time = new Date().toLocaleTimeString();
}, 1000);
registerDestructor(this, () => clearInterval(timer));
}
}
<p
x-data="{
time: new Date().toLocaleTimeString(),
timer: null,
init() { this.timer = setInterval(() => (this.time = new Date().toLocaleTimeString()), 1000) },
destroy() { clearInterval(this.timer) }
}"
>
Current time: <span x-text="time"></span>
</p>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Component composition
Props
<script>
import UserProfile from './UserProfile.svelte';
</script>
<UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />
<script>
export let name = '';
export let age = null;
export let favouriteColors = [];
export let isAvailable = false;
</script>
<p>My name is {name} !</p>
<p>My age is {age} !</p>
<p>My favourite colors are {favouriteColors.join(', ')} !</p>
<p>I am {isAvailable ? 'available' : 'not available'}</p>
React
import UserProfile from './UserProfile.jsx';
export default function App() {
return <UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />;
}
import PropTypes from 'prop-types';
export default function UserProfile({ name = '', age = null, favouriteColors = [], isAvailable = false }) {
return (
<>
<p>My name is {name} !</p>
<p>My age is {age} !</p>
<p>My favourite colors are {favouriteColors.join(', ')} !</p>
<p>I am {isAvailable ? 'available' : 'not available'}</p>
</>
);
}
UserProfile.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
favouriteColors: PropTypes.arrayOf(PropTypes.string).isRequired,
isAvailable: PropTypes.bool.isRequired,
};
<script setup>
import UserProfile from './UserProfile.vue';
</script>
<template>
<UserProfile
name="John"
:age="20"
:favourite-colors="['green', 'blue', 'red']"
is-available
/>
</template>
<script setup>
const props = defineProps({
name: {
type: String,
required: true,
default: '',
},
age: {
type: Number,
required: true,
default: null,
},
favouriteColors: {
type: Array,
required: true,
default: () => [],
},
isAvailable: {
type: Boolean,
required: true,
default: false,
},
});
</script>
<template>
<p>My name is {{ props.name }} !</p>
<p>My age is {{ props.age }} !</p>
<p>My favourite colors are {{ props.favouriteColors.join(', ') }} !</p>
<p>I am {{ props.isAvailable ? 'available' : 'not available' }}</p>
</template>
Angular
<app-userprofile name="John" [age]="20" [favouriteColors]="['green', 'blue', 'red']" [isAvailable]="true"> </app-userprofile>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {}
<p>My name is {{ name }} !</p>
<p>My age is {{ age }} !</p>
<p>My favourite colors are {{ favouriteColors.join(', ') }} !</p>
<p>I am {{ isAvailable ? 'available' : 'not available' }}</p>
import { Component, Input } from '@angular/core';
interface UserprofileComponentProps {
name: string;
age: number;
favouriteColors: string[];
isAvailable: boolean;
}
@Component({
selector: 'app-userprofile',
templateUrl: './userprofile.component.html',
styleUrls: ['./userprofile.component.css'],
})
export class UserprofileComponent implements UserprofileComponentProps {
@Input() name: string = '';
@Input() age: number = 0;
@Input() favouriteColors: string[] = [];
@Input() isAvailable: boolean = false;
}
import UserProfile from './UserProfile.jsx';
export default function App() {
return <UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />;
}
import { mergeProps } from 'solid-js';
export default function UserProfile(props) {
const merged = mergeProps({ name: '', age: null, favouriteColors: [], isAvailable: false }, props);
return (
<>
<p>My name is {merged.name} !</p>
<p>My age is {merged.age} !</p>
<p>My favourite colors are {merged.favouriteColors.join(', ')} !</p>
<p>I am {merged.isAvailable ? 'available' : 'not available'}</p>
</>
);
}
Lit
<!DOCTYPE html>
<head>
<script type="module" src="./x-app.js"></script>
</head>
<body>
<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
@customElement('user-profile')
export class UserProfile extends LitElement {
@property()
name = '';
@property({ type: Number })
age = null;
@property({ type: Array })
favouriteColors = [];
@property({ type: Boolean })
isAvailable = false;
render() {
return html`
<p>My name is ${this.name}</p>
<p>My age is ${this.age}</p>
<p>My favourite coloros are ${this.favouriteColors.join(', ')}</p>
<p>I am ${this.isAvailable ? 'available' : 'not available'}</p>
`;
}
}
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import './user-profile';
@customElement('x-app')
export class XApp extends LitElement {
render() {
return html`<user-profile name="John" age="20" .favouriteColors=${['green', 'blue', 'red']} isavailable></user-profile>`;
}
}
Ember
<UserProfile @name='John' @age={{20}} @favouriteColors={{array 'green' 'blue' 'red'}} @isAvailable={{true}} />
<p>My name is {{@name}} !</p>
<p>My age is {{@age}} !</p>
<p>My favourite colors are {{this.formattedColors}} !</p>
<p>I am {{if @isAvailable 'available' 'not available'}}</p>
import Component from '@glimmer/component';
export default class UserProfile extends Component {
get formattedColors() {
return this.args.favouriteColors.join(', ');
}
}
<!--Alpine JS suggests using a server-side templating engine or another frontend framework in conjunction with Alpine to do this-->
<div
x-data="{
name: 'John',
age: 20,
favouriteColors: ['green', 'blue', 'red'],
isAvailable: true
}"
>
<p>My name is <span x-text="John"></span></p>
<p>My age is <span x-text="age"></span></p>
<p>My favourite colors are <span x-text="favouriteColors.join(', ')"></span></p>
<p>I am <span x-text="isAvailable ? 'available' : 'not available'"></span></p>
</div>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Emit to parent
<script>
import AnswerButton from './AnswerButton.svelte';
let canCome = true;
function onAnswerNo() {
canCome = false;
}
function onAnswerYes() {
canCome = true;
}
</script>
<p>Can I come ?</p>
<AnswerButton on:yes={onAnswerYes} on:no={onAnswerNo} />
<p style="font-size: 50px;">{canCome ? '😀' : '😥'}</p>
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function clickYes() {
dispatch('yes');
}
function clickNo() {
dispatch('no');
}
</script>
<button on:click={clickYes}> YES </button>
<button on:click={clickNo}> NO </button>
React
import { useState } from 'react';
import AnswerButton from './AnswerButton.jsx';
export default function App() {
const [canCome, setCanCome] = useState(true);
function onAnswerNo() {
setCanCome(false);
}
function onAnswerYes() {
setCanCome(true);
}
return (
<>
<p>Can I come ?</p>
<AnswerButton onYes={onAnswerYes} onNo={onAnswerNo} />
<p style={{ fontSize: 50 }}>{canCome ? '😀' : '😥'}</p>
</>
);
}
import PropTypes from 'prop-types';
export default function AnswerButton({ onYes, onNo }) {
return (
<>
<button onClick={onYes}>YES</button>
<button onClick={onNo}>NO</button>
</>
);
}
AnswerButton.propTypes = {
onYes: PropTypes.func,
onNo: PropTypes.func,
};
<script setup>
import { ref } from 'vue';
import AnswerButton from './AnswerButton.vue';
let canCome = ref(true);
function onAnswerNo() {
canCome.value = false;
}
function onAnswerYes() {
canCome.value = true;
}
</script>
<template>
<p>Can I come ?</p>
<AnswerButton
@yes="onAnswerYes"
@no="onAnswerNo"
/>
<p style="font-size: 50px">
{{ canCome ? '😀' : '😥' }}
</p>
</template>
<script setup>
const emit = defineEmits(['yes', 'no']);
function clickYes() {
emit('yes');
}
function clickNo() {
emit('no');
}
</script>
<template>
<button @click="clickYes">
YES
</button>
<button @click="clickNo">
NO
</button>
</template>
Angular
<button (click)="yes.emit()">YES</button>
<button (click)="no.emit()">NO</button>
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-answer-button',
templateUrl: './answer-button.component.html',
})
export class AnswerButtonComponent {
@Output()
yes = new EventEmitter<void>();
@Output()
no = new EventEmitter<void>();
}
<p>Can I come ?</p>
<app-answer-button (yes)="onAnswerYes()" (no)="onAnswerNo()"> </app-answer-button>
<p style="font-size: 50px">{{ canCome ? '😀' : '😥' }}</p>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
canCome = true;
onAnswerYes() {
this.canCome = true;
}
onAnswerNo() {
this.canCome = false;
}
}
import { createSignal } from 'solid-js';
import AnswerButton from './AnswerButton.jsx';
export default function App() {
const [canCome, setCanCome] = createSignal(true);
function onAnswerNo() {
setCanCome(false);
}
function onAnswerYes() {
setCanCome(true);
}
return (
<>
<p>Can I come ?</p>
<AnswerButton onYes={onAnswerYes} onNo={onAnswerNo} />
<p style={{ 'font-size': '50px' }}>{canCome() ? '😀' : '😥'}</p>
</>
);
}
export default function AnswerButton(props) {
return (
<>
<button onClick={props.onYes}>YES</button>
<button onClick={props.onNo}>NO</button>
</>
);
}
Lit
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('answer-button')
export class AnswerButton extends LitElement {
clickYes() {
this.dispatchEvent(new Event('yes'));
}
clickNo() {
this.dispatchEvent(new Event('no'));
}
render() {
return html`
<button @click=${this.clickYes}>Yes</button>
<button @click=${this.clickNo}>No</button>
`;
}
}
<!DOCTYPE html>
<head>
<script type="module" src="./x-app.js"></script>
</head>
<body>
<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import './answer-button';
@customElement('x-app')
export class XApp extends LitElement {
@state()
canCome = true;
onAnswerNo() {
this.canCome = false;
}
onAnswerYes() {
this.canCome = true;
}
render() {
return html`
<p>Can I come ?</p>
<answer-button @yes=${this.onAnswerYes} @no=${this.onAnswerNo}></answer-button>
<p style="font-size: 50px;">${this.canCome ? '😀' : '😥'}</p>
`;
}
}
Ember
<button {{on 'click' @onYes}}> YES </button>
<button {{on 'click' @onNo}}> NO </button>
<p>Can I come ?</p>
<AnswerButton @onYes={{this.handleYes}} @onNo={{this.handleNo}} />
<p style='font-size: 50px;'>{{if this.canCome '😀' '😥'}}</p>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
export default class App extends Component {
@tracked canCome = true;
handleYes = () => (this.canCome = true);
handleNo = () => (this.canCome = false);
}
<div x-data="{ canCome: true }" x-on:yes="canCome = true" x-on:no="canCome = false">
<p>Can I come ?</p>
<div>
<button x-on:click="$dispatch('yes')">YES</button>
<button x-on:click="$dispatch('no')">NO</button>
</div>
<p style="font-size: 50px" x-text="canCome ? '😀' : '😥'"></p>
</div>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Slot
<script>
import FunnyButton from './FunnyButton.svelte';
</script>
<FunnyButton>Click me !</FunnyButton>
<button
style="background: rgba(0, 0, 0, 0.4); color: #fff; padding: 10px 20px; font-size: 30px; border: 2px solid #fff; margin: 8px; transform: scale(0.9); box-shadow: 4px 4px rgba(0, 0, 0, 0.4); transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s; outline: 0;"
>
<slot />
</button>
React
import FunnyButton from './FunnyButton.jsx';
export default function App() {
return <FunnyButton>Click me !</FunnyButton>;
}
import PropTypes from 'prop-types';
export default function FunnyButton({ children }) {
return (
<button
style={{
background: 'rgba(0, 0, 0, 0.4)',
color: '#fff',
padding: '10px 20px',
fontSize: '30px',
border: '2px solid #fff',
margin: '8px',
transform: 'scale(0.9)',
boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
outline: '0',
}}
>
{children}
</button>
);
}
FunnyButton.propTypes = {
children: PropTypes.node,
};
<script setup>
import FunnyButton from './FunnyButton.vue';
</script>
<template>
<FunnyButton> Click me ! </FunnyButton>
</template>
<template>
<button
style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
"
>
<slot />
</button>
</template>
Angular
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: '<app-funny-button>Click me !</app-funny-button>',
})
export class AppComponent {}
button {
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
}
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
styleUrls: ['./funny-button.component.css'],
template: `
<button>
<ng-content></ng-content>
</button>
`,
})
export class FunnyButtonComponent {}
import FunnyButton from './FunnyButton.jsx';
export default function App() {
return <FunnyButton>Click me !</FunnyButton>;
}
export default function FunnyButton(props) {
return (
<button
style={{
background: 'rgba(0, 0, 0, 0.4)',
color: '#fff',
padding: '10px 20px',
'font-size': '30px',
border: '2px solid #fff',
margin: '8px',
transform: 'scale(0.9)',
'box-shadow': '4px 4px rgba(0, 0, 0, 0.4)',
transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
outline: '0',
}}
>
{props.children}
</button>
);
}
Lit
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
@customElement('funny-button')
export class FunnyButton extends LitElement {
render() {
return html`
<button
style=${styleMap({
background: 'rgba(0, 0, 0, 0.4)',
color: '#fff',
padding: '10px 20px',
fontSize: '30px',
border: '2px solid #fff',
margin: '8px',
transform: 'scale(0.9)',
boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
outline: '0',
})}
>
<slot></slot>
</button>
`;
}
}
<!DOCTYPE html>
<head>
<script type="module" src="./x-app.js"></script>
</head>
<body>
<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import './funny-button';
@customElement('x-app')
export class XApp extends LitElement {
render() {
return html`<funny-button>Click me !</funny-button>`;
}
}
Ember
<FunnyButton> Click me ! </FunnyButton>
<button
style='
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;'
>
{{yield}}
</button>
<!--Alpine JS suggests using a server-side templating engine or another frontend framework in conjunction with Alpine to do this-->
<button
x-data
x-text="'Click me !'"
style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
"
>
<span>No content found</span>
</button>
Qwik
Missing snippet
Help us to improve Component Party 🎉
Slot fallback
<script>
import FunnyButton from './FunnyButton.svelte';
</script>
<FunnyButton />
<FunnyButton>I got content !</FunnyButton>
<button
style="background: rgba(0, 0, 0, 0.4); color: #fff; padding: 10px 20px; font-size: 30px; border: 2px solid #fff; margin: 8px; transform: scale(0.9); box-shadow: 4px 4px rgba(0, 0, 0, 0.4); transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s; outline: 0;"
>
<slot>
<span>No content found</span>
</slot>
</button>
React
import FunnyButton from './FunnyButton.jsx';
export default function App() {
return (
<>
<FunnyButton />
<FunnyButton>I got content !</FunnyButton>
</>
);
}
import PropTypes from 'prop-types';
export default function FunnyButton({ children }) {
return (
<button
style={{
background: 'rgba(0, 0, 0, 0.4)',
color: '#fff',
padding: '10px 20px',
fontSize: '30px',
border: '2px solid #fff',
margin: '8px',
transform: 'scale(0.9)',
boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
outline: '0',
}}
>
{children || <span>No content found</span>}
</button>
);
}
FunnyButton.propTypes = {
children: PropTypes.node,
};
<script setup>
import FunnyButton from './FunnyButton.vue';
</script>
<template>
<FunnyButton />
<FunnyButton> I got content ! </FunnyButton>
</template>
<template>
<button
style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
"
>
<slot>
<span>No content found</span>
</slot>
</button>
</template>
Angular
<app-funny-button></app-funny-button>
<app-funny-button>
<ng-template #content>I got content!</ng-template>
</app-funny-button>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {}
button {
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
}
import { Component, ContentChild, TemplateRef } from '@angular/core';
@Component({
selector: 'app-root',
styleUrls: ['./funny-button.component.css'],
template: `
<button>
<ng-container *ngIf="content; else fallback" [ngTemplateOutlet]="content"></ng-container>
<ng-template #fallback>
<span>No content found</span>
</ng-template>
</button>
`,
})
export class FunnyButtonComponent {
@ContentChild('content', { read: TemplateRef })
content?: TemplateRef<unknown>;
}
import FunnyButton from './FunnyButton.jsx';
export default function App() {
return (
<>
<FunnyButton />
<FunnyButton>I got content !</FunnyButton>
</>
);
}
export default function FunnyButton(props) {
return (
<button
style={{
background: 'rgba(0, 0, 0, 0.4)',
color: '#fff',
padding: '10px 20px',
'font-size': '30px',
border: '2px solid #fff',
margin: '8px',
transform: 'scale(0.9)',
'box-shadow': '4px 4px rgba(0, 0, 0, 0.4)',
transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
outline: '0',
}}
>
{props.children || <span>No content found</span>}
</button>
);
}
Lit
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
@customElement('funny-button')
export class FunnyButton extends LitElement {
render() {
return html`
<button
style=${styleMap({
background: 'rgba(0, 0, 0, 0.4)',
color: '#fff',
padding: '10px 20px',
fontSize: '30px',
border: '2px solid #fff',
margin: '8px',
transform: 'scale(0.9)',
boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
outline: '0',
})}
>
<slot>
<span>No content found</span>
</slot>
</button>
`;
}
}
<!DOCTYPE html>
<head>
<script type="module" src="./x-app.js"></script>
</head>
<body>
<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import './funny-button';
@customElement('x-app')
export class XApp extends LitElement {
render() {
return html`
<funny-button></funny-button>
<funny-button>Click me !</funny-button>
`;
}
}
Ember
<FunnyButton />
<FunnyButton>I got content !</FunnyButton>
<button
style='
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;'
>
{{