architecture
@Pick Avanzado
Un ejemplo mas amplio que combina servicios, ciclos de vida y composicion de componentes.
Resumen del ejemplo
Este documento prerenderizado muestra @Pick Avanzado como contenido HTML navegable. La experiencia interactiva se activa despues con el bundle del playground.
Vista previa del codigo
import pickStyles from "./pick.styles.css";
import pickTemplate from "./pick.template.html";
import {
Pick,
Services,
type IIntentSignal,
type InlineContext,
type PickComponent,
} from "pick-components";
import type { CatalogService, Product } from "./services.js";
interface CatalogState {
products: Product[];
refreshing: boolean;
}
type CatalogComponent = PickComponent &
CatalogState & {
refreshRequested$: IIntentSignal;
};
@Pick<CatalogState>("pick-example", (ctx: InlineContext<CatalogState>) => {
ctx.state({ products: [], refreshing: false });
ctx.intent("refreshRequested$");
ctx.initializer(
async function (component, deps) {
component.products = await deps!.catalog.loadCatalog();
},
() => ({ catalog: Services.get<CatalogService>("CatalogService") }),
);
ctx.lifecycle(
{
onInit(component, subs, deps) {
const catalog = deps!.catalog;
const host = component as CatalogComponent;
catalog.startStockUpdates();
subs.addSubscription(
catalog.onStockChange((updated) => {
component.products = updated;
}),
);
subs.addSubscription(
host.refreshRequested$.subscribe(() => {
void refreshCatalog(host, catalog);
}),
);
},
onDestroy(_component, _subs, deps) {
deps!.catalog.stopStockUpdates();
},
},
() => ({ catalog: Services.get<CatalogService>("CatalogService") }),
);
ctx.on({
refresh() {
(this as CatalogComponent).refreshRequested$.notify();
},
});
ctx.skeleton('<p aria-busy="true">Cargando catálogo...</p>');
ctx.errorTemplate('<p role="alert">Error al cargar el catálogo.</p>');
ctx.css(pickStyles);
ctx.html(pickTemplate);
})
class PickExample {}
async function refreshCatalog(
component: CatalogComponent,
catalog: CatalogService,
): Promise<void> {
component.refreshing = true;
component.products = await catalog.loadCatalog();
component.refreshing = false;
}