One view model. Two views.
Edit this form or use the ribbon. Both views share observable state, two-way bindings, and command availability.
Shared state connects the document and its ribbon. Try Bold, Font size, or a formatting preset.
Save writes this demo's document snapshot to this browser's local storage. Its asynchronous command disables itself while running. Edit the document to enable Save again.
Observable state
PascalCase and camelCase aliases address the same properties. The view updates when the
model raises PropertyChanged.
Command activity
Use the same component from an MVVM application
Use .NET-shaped observable objects and command classes.
const viewModel = new ObservableObject({
Title: 'Project brief', Bold: false
});
const save = new AsyncRelayCommand(
async () => persist(viewModel.toJSON()),
() => viewModel.Dirty
);
ribbon.dataContext = viewModel;
ribbon.model = new RibbonModel({ Tabs: [
new RibbonTab({ Id: 'home', Header: 'Home',
Groups: [new RibbonGroup({
Id: 'document', Header: 'Document',
Items: [new RibbonButton({
Id: 'save', Label: 'Save', Command: save
})]
})]
})
] });
Bindings and collection notifications connect controls and state.
new RibbonToggleButton({
Id: 'bold', Label: 'Bold',
Bindings: {
checked: new Binding('Bold', { mode: 'TwoWay' })
}
});
bind(titleInput, 'value', viewModel,
new Binding('Title', { mode: 'TwoWay' }));
const tools = new ObservableCollection();
tools.Add(new RibbonButton({
Id: 'new-tool', Label: 'New command'
}));
save.NotifyCanExecuteChanged();
The component also accepts plain JavaScript objects and emits composed DOM events for React, Vue, Svelte, and other hosts. The JavaScript API does not require .NET; a separate interop bridge supports Blazor applications.