view method
Renders the current model state for display.
This method is called after every update to refresh the screen. It should return either a String or a View object.
Guidelines
- Keep view functions pure - no side effects
- View should only depend on model state
- Use string interpolation or StringBuffer for complex views
- Consider terminal width/height for responsive layouts
Example
@override
String view() {
final buffer = StringBuffer();
// Header
buffer.writeln('╔════════════════════════════╗');
buffer.writeln('║ My Application ║');
buffer.writeln('╚════════════════════════════╝');
buffer.writeln();
// Content
if (loading) {
buffer.writeln('Loading...');
} else {
for (final item in items) {
final prefix = item == selectedItem ? '▸ ' : ' ';
buffer.writeln('$prefix$item');
}
}
buffer.writeln();
// Footer
buffer.writeln('↑/↓: Navigate Enter: Select q: Quit');
return buffer.toString();
}
Implementation
@override
String view() {
final buffer = StringBuffer();
// Prompt
buffer.writeln(styles.prompt.render(prompt));
// Input line
buffer.write(' Type "');
buffer.write(styles.activeChoice.render(confirmText));
buffer.write('": ');
// Current input with match highlighting
final expected = uni.graphemes(confirmText).toList(growable: false);
for (var i = 0; i < _input.length; i++) {
final typed = _input[i];
final exp = i < expected.length ? expected[i] : '';
final matches = caseSensitive
? typed == exp
: typed.toLowerCase() == exp.toLowerCase();
buffer.write(
(matches ? styles.activeChoice : Style().foreground(AnsiColor(9)))
.render(typed),
);
}
buffer.writeln();
// Error message
if (_error != null) {
buffer.writeln(Style().foreground(AnsiColor(9)).render(' $_error'));
}
// Help
if (showHelp) {
buffer.writeln(
styles.dimmed.render(' Press Enter to confirm, Esc to cancel'),
);
}
return buffer.toString();
}