I need widget with bpmn.js view: https://github.com/bpmn-io/bpmn-js
Used HtmlElementView:
// ignore: undefined_prefixed_name
ui.platformViewRegistry
.registerViewFactory('bpmn_view', (int viewId) => element);
return Column(
children: <Widget>[
Expanded(
child: HtmlElementView(key: UniqueKey(), viewType: "bpmn_view")),
],
);
With js:
const html = '''
<div id="canvas">canvas</div>
<script>
(function () {
window.addEventListener('view_bpmn', function (e) {
var bpmnJS = new BpmnJS({
container: "#canvas"
});
bpmnJS.importXML(e.details);
}, false);
}());
</script>
''';
element.setInnerHtml(html,
validator: NodeValidatorBuilder.common()..allowElement('script'));
But I get error when it execute:
VM4761 bpmn-viewer.development.js:18864 Uncaught TypeError: Cannot read property 'appendChild' of null
at Viewer.BaseViewer.attachTo (VM4761 bpmn-viewer.development.js:18864)
at Viewer.BaseViewer._init (VM4761 bpmn-viewer.development.js:18911)
at Viewer.BaseViewer (VM4761 bpmn-viewer.development.js:18454)
at new Viewer (VM4761 bpmn-viewer.development.js:19082)
at <anonymous>:3:25
at main.dart:185
at future.dart:316
at internalCallback (isolate_helper.dart:50)
And I can't set selector for BpmnJS like:
var bpmnJS = new BpmnJS({
container: "document.querySelector('flt-platform-view').shadowRoot.querySelector('#canvas')";
});
How can I make it work?
The Dart web platform supports calling JavaScript using the js package, also known as package:js. For help using the js package, see the following: Documentation for the js package: pub.
You can go to the pubspec. yaml file and add dependencies ,under dependencies and then packages get will do the work. or you can run flutter pub get in the terminal.
As an alternative to JavaScript or React Native, Google created the Flutter framework for cross-platform mobile application development. Flutter uses the Dart programming language which is not known by many developers. However, in contrast to React Native apps, apps built with Flutter look slick and much more native.
In a matter of minutes and without a single line of code, Buddy allows you to connect Node. js and Build Flutter app.
Since BpmnJS container
parameter accepts DOMElement type value, we can pass querySelector's result directly:
_element = html.DivElement()
..id = 'canvas'
..append(html.ScriptElement()
..text = """
const canvas = document.querySelector("flt-platform-view").shadowRoot.querySelector("#canvas");
const viewer = new BpmnJS({ container: canvas });
""");
// ignore: undefined_prefixed_name
ui.platformViewRegistry
.registerViewFactory('bpmn-view', (int viewId) => _element);
BpmnJS module should be attached to index.html file (in your project's top-level web folder):
<!DOCTYPE html>
<head>
<title>BpmnJS Demo</title>
<script defer src="main.dart.js" type="application/javascript"></script>
<script src="https://unpkg.com/[email protected]/dist/bpmn-navigated-viewer.development.js"></script>
</head>
...
Here is full code:
import 'dart:ui' as ui;
import 'package:universal_html/html.dart' as html;
import 'package:flutter/material.dart';
class BpmnDemo extends StatefulWidget {
@override
_BpmnDemoState createState() => _BpmnDemoState();
}
class _BpmnDemoState extends State<BpmnDemo> {
html.DivElement _element;
@override
void initState() {
super.initState();
_element = html.DivElement()
..id = 'canvas'
..append(html.ScriptElement()
..text = """
const canvas = document.querySelector("flt-platform-view").shadowRoot.querySelector("#canvas");
const viewer = new BpmnJS({ container: canvas });
const uri = "https://cdn.staticaly.com/gh/bpmn-io/bpmn-js-examples/dfceecba/url-viewer/resources/pizza-collaboration.bpmn";
fetch(uri).then(res => res.text().then(xml => viewer.importXML(xml)));
""");
// ignore: undefined_prefixed_name
ui.platformViewRegistry
.registerViewFactory('bpmn-view', (int viewId) => _element);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: HtmlElementView(key: UniqueKey(), viewType: "bpmn-view")),
);
}
}
UPDATE:
This example shows how to load a diagram from dart code and uses dart:js
library:
import 'dart:ui' as ui;
import 'dart:js' as js;
import 'package:universal_html/html.dart' as html;
import 'package:flutter/material.dart';
class BpmnDemo extends StatefulWidget {
@override
_BpmnDemoState createState() => _BpmnDemoState();
}
class _BpmnDemoState extends State<BpmnDemo> {
html.DivElement _element;
js.JsObject _viewer;
@override
void initState() {
super.initState();
_element = html.DivElement();
_viewer = js.JsObject(
js.context['BpmnJS'],
[
js.JsObject.jsify({'container': _element})
],
);
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory('bpmn-view', (int viewId) => _element);
loadDiagram('assets/pizza-collaboration.bpmn');
}
loadDiagram(String src) async {
final bundle = DefaultAssetBundle.of(context);
final xml = await bundle.loadString(src);
_viewer.callMethod('importXML', [xml]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(child: HtmlElementView(key: UniqueKey(), viewType: "bpmn-view")),
);
}
}
UPDATE 2:
Certain complications with calling methods from js library can arise when HtmlElementView
uses IFrame
element. In this case we can try two options:
callMethod
with saved context.IFrame
import 'dart:ui' as ui;
import 'dart:js' as js;
import 'dart:html' as html;
import 'package:flutter/material.dart';
class IFrameDemoPage extends StatefulWidget {
@override
_IFrameDemoPageState createState() => _IFrameDemoPageState();
}
class _IFrameDemoPageState extends State<IFrameDemoPage> {
html.IFrameElement _element;
js.JsObject _connector;
@override
void initState() {
super.initState();
js.context["connect_content_to_flutter"] = (content) {
_connector = content;
};
_element = html.IFrameElement()
..style.border = 'none'
..srcdoc = """
<!DOCTYPE html>
<head>
<script>
// variant 1
parent.connect_content_to_flutter && parent.connect_content_to_flutter(window)
function hello(msg) {
alert(msg)
}
// variant 2
window.addEventListener("message", (message) => {
if (message.data.id === "test") {
alert(message.data.msg)
}
})
</script>
</head>
<body>
<h2>I'm IFrame</h2>
</body>
</html>
""";
// ignore:undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'example',
(int viewId) => _element,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.filter_1),
tooltip: 'Test with connector',
onPressed: () {
_connector.callMethod('hello', ['Hello from first variant']);
},
),
IconButton(
icon: Icon(Icons.filter_2),
tooltip: 'Test with postMessage',
onPressed: () {
_element.contentWindow.postMessage({
'id': 'test',
'msg': 'Hello from second variant',
}, "*");
},
)
],
),
body: Container(
child: HtmlElementView(viewType: 'example'),
),
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With