--- title: Flutter pagination_prev: demos/static/index pagination_next: demos/desktop/index sidebar_position: 5 sidebar_custom_props: summary: Dart + JS Interop --- import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; Dart + Flutter is a cross-platform alternative to [JS + React Native](/docs/demos/mobile/reactnative). For the iOS and Android targets, the `flutter_js` package wraps JavaScriptCore and QuickJS engines respectively. The [Standalone scripts](/docs/getting-started/installation/standalone) can be parsed and evaluated in the wrapped engines. The "Complete Example" creates an app that looks like the screenshots below:
iOS
![iOS screenshot](pathname:///flutter/ios.png)
:::warning Telemetry Before starting this demo, manually disable telemetry. On MacOS: ```bash dart --disable-telemetry dart --disable-analytics flutter config --no-analytics flutter config --disable-telemetry ``` ::: ## Integration Details This demo assumes familiarity with Dart and Flutter. ### Loading SheetJS #### Adding the scripts The `flutter.assets` property in `pubspec.yaml` specifies assets. Assuming the standalone script and shim are placed in the `scripts` folder, the following snippet loads the scripts as assets: ```yaml title="pubspec.yaml" flutter: assets: - scripts/xlsx.full.min.js - scripts/shim.min.js ``` Once loaded, the contents can be loaded with `rootBundle.loadString`: ```dart import 'package:flutter/services.dart' show rootBundle; String shim = await rootBundle.loadString("scripts/shim.min.js"); String sheetjs = await rootBundle.loadString("scripts/xlsx.full.min.js"); ``` #### Initialization It is strongly recommended to add the engine to the state of a `StatefulWidget`: ```dart import 'package:flutter_js/flutter_js.dart'; class SheetJSFlutterState extends State { // highlight-next-line late JavascriptRuntime _engine; @override void initState() { // highlight-next-line _engine = getJavascriptRuntime(); } } ``` #### Running SheetJS Scripts Since fetching assets is asychronous, it is recommended to create a wrapper `async` function and sequentially await each script: ```dart class SheetJSFlutterState extends State { String _version = '0.0.0'; @override void initState() { _engine = getJavascriptRuntime(); _initEngine(); // note: this is not `await`-ed } Future _initEngine() async { /* fetch and evaluate the shim */ String shim = await rootBundle.loadString("scripts/shim.min.js"); _engine.evaluate(shim); // highlight-start /* fetch and evaluate the main script */ String sheetjs = await rootBundle.loadString("scripts/xlsx.full.min.js"); _engine.evaluate(sheetjs); // highlight-end /* capture the version string */ JsEvalResult vers = _engine.evaluate("XLSX.version"); setState(() => _version = vers.stringResult); } } ``` ### Reading data The most common binary data type in Dart is `Uint8List`. It is the data type for `http.Response#bodyBytes` and the return type of `File#readAsBytes()`. The Flutter JS connector offers no simple interop for `Uint8List` data. The data should be converted to Base64 before parsing. The `csv` package provides a special `CsvToListConverter` converter to generate `List>` (Dart's spiritual equivalent of the array of arrays): ```dart import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:csv/csv.dart'; class SheetJSFlutterState extends State { List> _data = []; void _processBytes(Uint8List bytes) { String base64 = base64Encode(bytes); JsEvalResult func = _engine.evaluate(""" var wb = XLSX.read('$base64'); XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]); """); String csv = func.stringResult; setState(() { _data = CsvToListConverter(eol: "\n").convert(csv); }); } ``` ## Demo :::note This demo was tested on an Intel Mac on 2023 May 31 with Flutter 3.10.2, Dart 3.0.2, and `flutter_js` 0.7.0 The iOS simulator runs iOS 16.2 on an iPhone 14 Pro Max. ::: ### Base Project 1) Disable telemetry. ```bash dart --disable-telemetry dart --disable-analytics flutter config --no-analytics flutter config --disable-telemetry ``` 2) Create a new Flutter project: ```bash flutter create sheetjs_flutter cd sheetjs_flutter ``` 3) Open the iOS simulator 4) While the iOS simulator is open, start the application: ```bash flutter run ``` Once the app loads in the simulator, stop the terminal process. 5) Install Flutter / Dart dependencies: ```bash flutter pub add http csv flutter_js ``` 6) Open `pubspec.yaml` with a text editor. Search for the line that starts with `flutter:` (no whitespace) and add the highlighted lines: ```yaml title="pubspec.yaml" # The following section is specific to Flutter packages. flutter: // highlight-start assets: - scripts/xlsx.full.min.js - scripts/shim.min.js // highlight-end ``` 7) Download dependencies to the `scripts` folder: {`\ mkdir -p scripts cd scripts curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js cd ..`} 8) Download [`main.dart`](pathname:///flutter/main.dart) to `lib/main.dart`: ```bash curl -L -o lib/main.dart https://docs.sheetjs.com/flutter/main.dart ``` 9) Launch the app: ```bash flutter run ``` The app fetches , parses, converts data to an array of arrays, and presents the data in a Flutter `Table` widget.