view method

  1. @override
String view()
override

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 w = width;
  final h = height ?? _visibleLines().length;

  if (w == 0 || h == 0) {
    return '';
  }

  final contentWidth = w - style.getHorizontalFrameSize;
  final contentHeight = h - style.getVerticalFrameSize;

  final visible = _visibleLines();
  var contents = visible.join('\n');

  // Pad to width and height using Style
  contents = Style()
      .width(contentWidth)
      .height(contentHeight)
      .render(contents);

  var rendered = style.unsetWidth().unsetHeight().render(contents);
  // Defensive: ensure we don't leak any active SGR state to whatever gets
  // rendered after this component (e.g. when wrapping + height truncation
  // drops a trailing reset).
  if (rendered.contains(Ansi.escape)) {
    rendered = '$rendered${Ansi.reset}';
  }
  return rendered;
}