3.1. Quickstart¶
Each flavor exposes the same shape: wire a message hub and dispatcher, build a
leaf ComponentVM, then compose child tabs in a CompositeVM.
IMessageHub hub = new MessageHub();
IDispatcher dispatcher = RxDispatcher.Immediate();
var homeTab = ComponentVM<TabModel>.Builder()
.Name("home-tab")
.Model(new TabModel("Home"))
.Services(hub, dispatcher)
.Build();
var settingsTab = ComponentVM<TabModel>.Builder()
.Name("settings-tab")
.Model(new TabModel("Settings"))
.Services(hub, dispatcher)
.Build();
var tabs = CompositeVM<ComponentVM<TabModel>>.Builder()
.Name("tab-bar")
.Services(hub, dispatcher)
.Children(() => [homeTab, settingsTab])
.Build();
tabs.Construct();
tabs.Current = settingsTab;
hub = MessageHub()
dispatcher = RxDispatcher.immediate()
home_tab = (
ComponentVMOf.builder()
.name("home-tab")
.model(TabModel("Home"))
.services(hub, dispatcher)
.build()
)
settings_tab = (
ComponentVMOf.builder()
.name("settings-tab")
.model(TabModel("Settings"))
.services(hub, dispatcher)
.build()
)
tabs = (
CompositeVM.builder()
.name("tab-bar")
.services(hub, dispatcher)
.children(lambda: [home_tab, settings_tab])
.build()
)
tabs.construct()
tabs.current = settings_tab
const hub = new MessageHub();
const dispatcher = RxDispatcher.immediate();
const homeTab = ComponentVMOf.builder<TabModel>()
.name("home-tab")
.model({ title: "Home" })
.services(hub, dispatcher)
.build();
const settingsTab = ComponentVMOf.builder<TabModel>()
.name("settings-tab")
.model({ title: "Settings" })
.services(hub, dispatcher)
.build();
const tabs = CompositeVM.builder<ComponentVMOf<TabModel>>()
.name("tab-bar")
.services(hub, dispatcher)
.children(() => [homeTab, settingsTab])
.build();
tabs.construct();
tabs.current = settingsTab;
let hub = MessageHub()
let dispatcher = ImmediateDispatcher.INSTANCE
let homeTab = try ComponentVMOf<TabModel>.builder()
.name("home-tab")
.model(TabModel(title: "Home"))
.services(hub: hub, dispatcher: dispatcher)
.build()
let settingsTab = try ComponentVMOf<TabModel>.builder()
.name("settings-tab")
.model(TabModel(title: "Settings"))
.services(hub: hub, dispatcher: dispatcher)
.build()
let tabs = try CompositeVM<ComponentVMOf<TabModel>>.builder()
.name("tab-bar")
.services(hub: hub, dispatcher: dispatcher)
.children { [homeTab, settingsTab] }
.build()
try tabs.construct()
tabs.current = settingsTab
use vmx::{ComponentVm, CompositeVm, MessageHub, NullDispatcher, VmxResult};
#[derive(Clone, PartialEq)]
struct TabModel {
title: String,
}
fn main() -> VmxResult<()> {
let hub = MessageHub::new();
let dispatcher = NullDispatcher::new();
let home_tab = ComponentVm::with_model(
"home-tab",
TabModel { title: "Home".to_string() },
hub.clone(),
dispatcher,
);
let settings_tab = ComponentVm::with_model(
"settings-tab",
TabModel { title: "Settings".to_string() },
hub.clone(),
dispatcher,
);
let tabs = CompositeVm::with_services("tab-bar", hub, dispatcher);
tabs.add(home_tab.clone())?;
tabs.add(settings_tab.clone())?;
tabs.construct()?;
tabs.select_component(&settings_tab)
}
3.1.1. What This Shows¶
- One spec and five idiomatic source surfaces.
- Builders/direct construction stay idiomatic per flavor.
- Construction and selection semantics stay aligned even as naming changes.