Migrating to package:web
AngularDart 9.0 introduces a breaking change: all DOM APIs have been migrated from dart:html to package:web. This guide covers everything you need to know to migrate your application.
Why the Change?
dart:html has been deprecated by the Dart team in favor of package:web, which provides:
- Better JS interop — Direct compatibility with JavaScript types via
dart:js_interop - Smaller output — More efficient compilation to JavaScript
- Modern API — Aligned with current web standards
- Future-proof —
dart:htmlwill be removed in a future Dart SDK version
What Changed
Import Changes
Replace all dart:html imports with package:web:
// Before (AngularDart 8.x)
import 'dart:html' as html;
// After (AngularDart 9.x)
import 'package:web/web.dart' as web;
Type Changes
All DOM types have been renamed:
| dart:html (8.x) | package:web (9.x) |
|---|---|
html.Element |
web.Element |
html.HtmlElement |
web.HTMLElement |
html.DivElement |
web.HTMLDivElement |
html.SpanElement |
web.HTMLSpanElement |
html.InputElement |
web.HTMLInputElement |
html.ButtonElement |
web.HTMLButtonElement |
html.AnchorElement |
web.HTMLAnchorElement |
html.ImageElement |
web.HTMLImageElement |
html.Document |
web.Document |
html.Window |
web.Window |
html.Event |
web.Event |
html.MouseEvent |
web.MouseEvent |
html.KeyboardEvent |
web.KeyboardEvent |
API Changes
Several DOM APIs have changed:
// element.classes → element.classList
element.classes.add('active'); // Before
element.classList.add('active'); // After
// element.parent → element.parentNode
html.Element? parent = element.parent; // Before
web.Node? parent = element.parentNode; // After
// element.remove() → parentNode?.removeChild()
element.remove(); // Before
element.parentNode?.removeChild(element); // After
// innerHTML setter requires .toJS
element.innerHtml = '<p>Hello</p>'; // Before
element.innerHTML = '<p>Hello</p>'.toJS; // After (requires dart:js_interop)
// console.log requires .toJS for strings
html.window.console.log('Hello'); // Before
web.console.log('Hello'.toJS); // After
Event Listeners
Event listeners now require .toJS conversion:
import 'dart:js_interop';
// Before (dart:html)
element.onClick.listen((event) {
print('Clicked!');
});
// After (package:web)
element.addEventListener('click', (web.Event event) {
print('Clicked!');
}.toJS);
NodeTreeSanitizer Removed
NodeTreeSanitizer has been removed. Use template + innerHTML instead:
// Before (AngularDart 8.x)
element.setInnerHtml(htmlContent, treeSanitizer: NodeTreeSanitizer.trusted);
// After (AngularDart 9.x)
element.innerHTML = htmlContent.toJS;
Step-by-Step Migration
1. Update Dependencies
dependencies:
angulardart: '>=9.0.0 <10.0.0'
web: '>=1.0.0 <2.0.0'
dev_dependencies:
angulardart_compiler: '>=5.0.0 <6.0.0'
2. Update SDK Constraint
environment:
sdk: '>=3.4.0 <4.0.0'
3. Replace Imports
Search and replace across your codebase:
# Find all files using dart:html
grep -r "dart:html" lib/
# Replace in each file
# import 'dart:html' as html; → import 'package:web/web.dart' as web;
4. Update Type References
Replace all html.* type references with web.*:
# Find all html.* references
grep -r "html\." lib/
5. Fix API Calls
Update the changed APIs (see table above).
6. Add dart:js_interop Import
For files using .toJS, add:
import 'dart:js_interop';
7. Fix Event Listeners
Convert all event listeners to use .toJS:
// Before
element.onClick.listen(handler);
// After
element.addEventListener('click', handler.toJS);
8. Run dart analyze
dart analyze
Fix any remaining issues.
Common Issues
"The argument type 'void Function(dynamic)' can't be assigned to 'JSFunction?'"
This means you need to add .toJS to your event handler:
// Wrong
element.addEventListener('click', handler);
// Correct
element.addEventListener('click', handler.toJS);
"The method 'toDart' isn't defined for 'JSFunction'"
Use explicit type conversion instead:
// Wrong
final handler = jsFunction.toDart;
// Correct
final handler = (jsFunction as JSFunction).toDart<void Function(web.Event)>();
"A value of type 'ElementRef' can't be assigned to 'HTMLElement'"
ElementRef.nativeElement returns Object in AngularDart 9.x. Cast explicitly:
final element = elementRef.nativeElement as web.HTMLElement;
Third-Party Packages
If you use third-party packages that depend on dart:html, check for updated versions that support package:web. Common packages:
| Package | package:web compatible version |
|---|---|
angulardart |
>=9.0.0 <10.0.0 |
angulardart_components |
>=3.0.0 <4.0.0 |
angulardart_router |
>=5.0.0 <6.0.0 |
angulardart_forms |
>=6.0.0 <7.0.0 |
See Also
- AngularDart 9.0 Changelog — Full list of changes
- package:web documentation — Official package:web docs
- Dart JS interop guide — Understanding
.toJSand JS types