dart:html library provides HTML elements and other resources for web-based applications. This library enables DOM manipulation, event handling, and browser API access.
Platform Availability: dart:html is only available on web platforms. It cannot be used in Flutter or command-line applications. For server-side or mobile apps, use dart:io instead.
Overview
To use this library in your code:import 'dart:html';
- DOM manipulation (elements, nodes, attributes)
- Event handling
- Browser APIs (Storage, Canvas, WebSocket, etc.)
- HTTP requests (HttpRequest)
- CSS and styling
DOM Manipulation
Selecting Elements
Returns the first element that matches the CSS selector.
Returns all elements that match the CSS selector.
import 'dart:html';
// Select by ID
var button = querySelector('#myButton');
// Select by class
var items = querySelectorAll('.item');
// Select by tag
var paragraphs = querySelectorAll('p');
// Complex selectors
var navLinks = querySelectorAll('nav ul li a');
var activeItems = querySelectorAll('.item.active');
// Get element by ID (alternative)
var element = document.getElementById('myId');
// Type-safe selection
ButtonElement? button = querySelector('#myButton') as ButtonElement?;
if (button != null) {
button.click();
}
Creating Elements
// Create element
var div = DivElement();
var paragraph = ParagraphElement();
var button = ButtonElement();
var input = InputElement();
// Set properties
button.text = 'Click Me';
button.id = 'submitButton';
button.classes.add('btn-primary');
input.type = 'text';
input.placeholder = 'Enter name';
input.value = 'Default value';
// Set attributes
div.setAttribute('data-id', '123');
var dataId = div.getAttribute('data-id');
// Create with HTML
var container = DivElement()
..innerHTML = '<p>Hello, <strong>World</strong>!</p>';
Modifying DOM
DOM Modification Methods
DOM Modification Methods
// Append child
var parent = querySelector('#parent')!;
var child = DivElement()..text = 'Child element';
parent.append(child);
// Insert before
var sibling = querySelector('#sibling')!;
parent.insertBefore(child, sibling);
// Remove element
child.remove();
// Replace element
var newElement = SpanElement()..text = 'Replacement';
child.replaceWith(newElement);
// Clear all children
parent.children.clear();
// Clone element
var clone = child.clone(true); // true = deep clone
// Move element
var newParent = querySelector('#newParent')!;
newParent.append(child); // Moves from old parent
Element Properties
var element = querySelector('#myElement')!;
// Text content
element.text = 'Plain text';
var text = element.text;
// HTML content
element.innerHtml = '<strong>Bold</strong> text';
var html = element.innerHtml;
// Classes
element.classes.add('active');
element.classes.remove('hidden');
element.classes.toggle('selected');
if (element.classes.contains('active')) {
print('Element is active');
}
// Styles
element.style.color = 'red';
element.style.fontSize = '16px';
element.style.display = 'none';
// Data attributes
element.dataset['userId'] = '123';
var userId = element.dataset['userId'];
// Dimensions and position
var width = element.clientWidth;
var height = element.clientHeight;
var rect = element.getBoundingClientRect();
print('Top: ${rect.top}, Left: ${rect.left}');
Event Handling
Click Events
// Add click listener
var button = querySelector('#myButton')!;
button.onClick.listen((event) {
print('Button clicked!');
event.preventDefault(); // Prevent default action
});
// One-time event
button.onClick.first.then((event) {
print('First click');
});
// Remove listener (store subscription)
var subscription = button.onClick.listen((event) {
print('Click');
});
subscription.cancel(); // Remove listener
Common Events
Event Types
Event Types
var input = querySelector('#myInput') as InputElement;
var form = querySelector('#myForm') as FormElement;
// Input events
input.onInput.listen((event) {
print('Input value: ${input.value}');
});
input.onChange.listen((event) {
print('Input changed');
});
input.onFocus.listen((event) {
print('Input focused');
});
input.onBlur.listen((event) {
print('Input blurred');
});
// Keyboard events
input.onKeyPress.listen((event) {
print('Key pressed: ${event.charCode}');
});
input.onKeyDown.listen((event) {
if (event.keyCode == KeyCode.ENTER) {
print('Enter pressed');
}
});
// Mouse events
var element = querySelector('#myElement')!;
element.onMouseEnter.listen((event) => print('Mouse entered'));
element.onMouseLeave.listen((event) => print('Mouse left'));
element.onMouseMove.listen((event) {
print('Mouse at: ${event.client.x}, ${event.client.y}');
});
// Form events
form.onSubmit.listen((event) {
event.preventDefault();
print('Form submitted');
});
form.onReset.listen((event) {
print('Form reset');
});
// Window events
window.onResize.listen((event) {
print('Window resized: ${window.innerWidth}x${window.innerHeight}');
});
window.onLoad.listen((event) {
print('Page loaded');
});
Event Delegation
// Handle events on parent for dynamically added children
var list = querySelector('#itemList')!;
list.onClick.listen((event) {
var target = event.target as Element;
if (target.classes.contains('item')) {
print('Item clicked: ${target.text}');
}
});
Forms and Input
Form Handling
var form = querySelector('#myForm') as FormElement;
var nameInput = querySelector('#name') as InputElement;
var emailInput = querySelector('#email') as InputElement;
var submitButton = querySelector('#submit') as ButtonElement;
// Handle form submission
form.onSubmit.listen((event) {
event.preventDefault();
// Get form data
var name = nameInput.value;
var email = emailInput.value;
// Validate
if (name.isEmpty || email.isEmpty) {
window.alert('Please fill all fields');
return;
}
// Submit data
submitForm(name, email);
});
// Reset form
form.reset();
// Enable/disable form elements
submitButton.disabled = true;
nameInput.disabled = false;
Input Types
// Text input
var textInput = InputElement()
..type = 'text'
..placeholder = 'Enter text';
// Number input
var numberInput = InputElement()
..type = 'number'
..min = '0'
..max = '100'
..step = '1';
// Checkbox
var checkbox = InputElement()
..type = 'checkbox'
..checked = true;
if (checkbox.checked!) {
print('Checkbox is checked');
}
// Radio buttons
var radio1 = InputElement()
..type = 'radio'
..name = 'choice'
..value = 'option1';
// Select dropdown
var select = SelectElement();
select.append(OptionElement()
..value = '1'
..text = 'Option 1');
select.append(OptionElement()
..value = '2'
..text = 'Option 2');
var selectedValue = select.value;
HTTP Requests
HttpRequest (Ajax)
Makes HTTP requests to servers. Similar to XMLHttpRequest in JavaScript.
import 'dart:html';
import 'dart:convert';
// GET request
Future<Map<String, dynamic>> fetchData() async {
try {
var response = await HttpRequest.getString('https://api.example.com/data');
return jsonDecode(response);
} catch (e) {
print('Error: $e');
rethrow;
}
}
// POST request
Future<void> postData(Map<String, dynamic> data) async {
var request = HttpRequest();
request.open('POST', 'https://api.example.com/submit');
request.setRequestHeader('Content-Type', 'application/json');
request.onLoad.listen((event) {
if (request.status == 200) {
print('Success: ${request.responseText}');
} else {
print('Error: ${request.status}');
}
});
request.send(jsonEncode(data));
}
// With progress tracking
Future<void> uploadFile(File file) async {
var request = HttpRequest();
request.open('POST', 'https://api.example.com/upload');
request.upload.onProgress.listen((event) {
var percent = (event.loaded / event.total!) * 100;
print('Upload progress: ${percent.toStringAsFixed(1)}%');
});
request.send(file);
}
Local Storage
Persistent key-value storage that survives browser restarts.
Session-only key-value storage that clears when the tab closes.
import 'dart:html';
// Local storage (persists)
window.localStorage['username'] = 'john_doe';
var username = window.localStorage['username'];
window.localStorage.remove('username');
window.localStorage.clear();
// Session storage (tab-specific)
window.sessionStorage['tempData'] = 'value';
// Store JSON data
var data = {'name': 'John', 'age': 30};
window.localStorage['userData'] = jsonEncode(data);
var stored = window.localStorage['userData'];
if (stored != null) {
var userData = jsonDecode(stored);
print(userData['name']);
}
// Check if key exists
if (window.localStorage.containsKey('username')) {
print('Username exists');
}
// Get all keys
for (var key in window.localStorage.keys) {
print('$key: ${window.localStorage[key]}');
}
Window and Document
Window Object
// Window properties
print('Width: ${window.innerWidth}');
print('Height: ${window.innerHeight}');
print('URL: ${window.location.href}');
// Navigation
window.location.href = 'https://example.com';
window.location.reload();
window.history.back();
window.history.forward();
// Dialogs
window.alert('Hello!');
var confirmed = window.confirm('Are you sure?');
var input = window.prompt('Enter your name:');
// Timers
var timerId = window.setTimeout(() {
print('Delayed execution');
}, 1000);
var intervalId = window.setInterval(() {
print('Repeated execution');
}, 1000);
window.clearTimeout(timerId);
window.clearInterval(intervalId);
// Console
window.console.log('Log message');
window.console.error('Error message');
window.console.warn('Warning message');
Document Object
// Document properties
var title = document.title;
document.title = 'New Title';
var url = document.baseUri;
var domain = document.domain;
// Document ready
document.onReadyStateChange.listen((event) {
if (document.readyState == 'complete') {
print('Document loaded');
}
});
// Create elements
var element = document.createElement('div');
var textNode = document.createTextNode('Text content');
// Body
document.body?.append(element);
Canvas
HTML5 Canvas for drawing graphics.
var canvas = querySelector('#myCanvas') as CanvasElement;
var ctx = canvas.context2D;
// Draw rectangle
ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 100, 50);
// Draw circle
ctx.beginPath();
ctx.arc(150, 75, 50, 0, 2 * 3.14159);
ctx.fillStyle = 'red';
ctx.fill();
// Draw line
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(200, 100);
ctx.strokeStyle = 'green';
ctx.lineWidth = 2;
ctx.stroke();
// Draw text
ctx.font = '20px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas', 10, 100);
// Clear canvas
ctx.clearRect(0, 0, canvas.width!, canvas.height!);
WebSocket
Enables real-time bidirectional communication with a server.
var ws = WebSocket('wss://echo.websocket.org');
// Connection opened
ws.onOpen.listen((event) {
print('Connected');
ws.send('Hello Server!');
});
// Receive messages
ws.onMessage.listen((MessageEvent event) {
print('Received: ${event.data}');
});
// Connection closed
ws.onClose.listen((event) {
print('Disconnected');
});
// Error handling
ws.onError.listen((event) {
print('Error occurred');
});
// Close connection
ws.close();
Best Practices
- Always null-check querySelector results before using them
- Use event delegation for dynamically created elements
- Cancel subscriptions when elements are removed to prevent memory leaks
- Sanitize user input before inserting into DOM to prevent XSS
- Use typed elements (ButtonElement, InputElement) for type safety
For complex web apps, consider using a web framework like AngularDart or over_react instead of manipulating the DOM directly with dart:html.
Common Patterns
// Safe element access
void updateElement() {
var element = querySelector('#myElement');
if (element != null) {
element.text = 'Updated';
}
}
// Event delegation for dynamic content
void setupList() {
var list = querySelector('#list')!;
// Handle clicks on current and future items
list.onClick.listen((event) {
var target = event.target as Element;
if (target.classes.contains('item')) {
handleItemClick(target);
}
});
}
// Loading state management
Future<void> loadData() async {
var button = querySelector('#loadButton') as ButtonElement;
var spinner = querySelector('#spinner')!;
button.disabled = true;
spinner.classes.remove('hidden');
try {
await fetchData();
} finally {
button.disabled = false;
spinner.classes.add('hidden');
}
}
Related Resources
- Web Programming with Dart - Official web guide
- AngularDart - Web framework for Dart
- MDN Web Docs - HTML/CSS/JavaScript reference