Events & Slots
@Emit(propName)
Binds a method and calls the named prop callback with its return value. Handles this binding automatically.
tsx
@Component()
class SearchInput extends StatefulComponent {
@Prop() onSearch?: (query: string) => void
@State() value = ''
@Emit('onSearch')
handleSubmit() {
return this.value // passed to onSearch prop
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input value={() => this.value}
onInput={(e) => { this.value = (e.target as HTMLInputElement).value }} />
<button type="submit">Search</button>
</form>
)
}
}
// Usage:
<SearchInput onSearch={(q) => console.log('searching:', q)} />Exposing the prop type without @Prop
If you don't use @Prop for the callback, declare the prop type with declare so it appears in JSX:
tsx
@Component()
class Modal extends StatefulComponent {
@Emit('onClose')
handleClose() { /* ... */ }
declare onClose: (() => void) | undefined // makes onClose appear in <Modal> props
}@Slot(name?)
Declares a named slot. Returns the children distributed into that slot. Omit the name for the default slot.
tsx
import type { Children } from '@praxisjs/shared'
@Component()
class Card extends StatefulComponent {
@Slot() default!: Children
@Slot('header') header?: Children
@Slot('footer') footer?: Children
render() {
return (
<div class="card">
{this.header && <header>{this.header}</header>}
<main>{this.default}</main>
{this.footer && <footer>{this.footer}</footer>}
</div>
)
}
}
// Usage:
<Card>
<span slot="header">Title</span>
<p>Body content</p>
<span slot="footer">Footer text</span>
</Card>@OnCommand(propName)
Subscribes the decorated method to a Command prop — an imperative event bus for triggering component actions from the outside. Auto-unsubscribes on unmount.
tsx
import { Command, createCommand } from '@praxisjs/decorators'
@Component()
class VideoPlayer extends StatefulComponent {
@Prop() play?: Command
@Prop() pause?: Command
@OnCommand('play')
handlePlay() {
this.isPlaying = true
}
@OnCommand('pause')
handlePause() {
this.isPlaying = false
}
}
// Usage:
const play = createCommand()
const pause = createCommand()
<VideoPlayer play={play} pause={pause} />
// Trigger from outside:
play.trigger()
pause.trigger()Command<T> with payload
ts
const seek = createCommand<number>()
seek.trigger(45.2) // seek to 45.2 seconds
// Subscribe manually:
seek.subscribe((time) => console.log('seek to', time))