piano_templates 1.0.2
piano_templates: ^1.0.2 copied to clipboard
Piano Templates SDK for Flutter.
Piano Templates SDK for Flutter #
Display Piano templates, forms, and recommendations returned by Piano Composer.
Each type is shown in a WebView, either as a modal or inline.
Installation #
Add the dependency to your pubspec.yaml:
dependencies:
piano_templates: ^1.0.2
Getting Started #
piano_templates builds on piano_common
and piano_composer, so you need a
Piano instance first:
import 'package:piano_common/piano_common.dart';
import 'package:piano_templates/piano_templates.dart';
final piano = await Piano.init(
endpoint: PianoEndpoint.production,
aid: '<AID>',
);
Get a client via piano.templates():
final templates = piano.templates();
It creates three controllers, one for each kind of Composer show event:
| Controller | Type | Handles event |
|---|---|---|
templates.template() |
PianoShowTemplateController |
PianoComposerShowTemplate |
templates.form() |
PianoShowFormController |
PianoComposerShowForm |
templates.recommendations() |
PianoShowRecommendationsController |
PianoComposerShowRecommendations |
The factory methods take no arguments. All per-show options are passed to
show via a typed parameters object:
Future<R?> show(
PianoComposerEvent<T> event,
BuildContext context, [
P? params,
]);
The params you pass are retained on controller.params, so callbacks
(such as JS-bridge listeners or the form's signIn) keep working after
show returns. A later show call that omits params reuses the last ones.
Templates #
Create a controller, then call show with the event and a BuildContext:
final controller = templates.template();
// When a PianoComposerShowTemplate event arrives:
await controller.show(event, context);
Listening to template events #
A template can send events over the JavaScript bridge (for example, when the
user logs in or closes it). Pass a PianoTemplateListener via
PianoShowTemplateParams to handle them:
final controller = templates.template();
await controller.show(
event,
context,
PianoShowTemplateParams(
listener: PianoTemplateListener(
onClose: (data) => print('Closed'),
onCloseAndRefresh: (data) => print('Closed, refresh the page'),
onRegister: (data) => print('User registered'),
onLogin: (data) => print('User logged in'),
onLogout: (data) => print('User logged out'),
onCustomEvent: (data) => print('Custom event: $data'),
onTerminateSession: (session) {
print('Terminate session: ${session.token}');
},
),
),
);
onTerminateSession receives a PianoTerminateSession with token,
sessionCount, and sessionLimit.
Reloading with a new token #
show returns a PianoShowTemplateResult you can use to reload the template
with a new user token, without reloading the whole page:
final result = await controller.show(event, context);
result?.reloadWithToken('<user_token>');
Forms #
Show a Piano ID form. Pass a PianoShowFormParams with callbacks to react to
its lifecycle:
final controller = templates.form();
await controller.show(
event,
context,
PianoShowFormParams(
accessToken: '<access_token>',
onClose: () => print('Form closed'),
signIn: (context) async {
// Called when the form rejects the current token and needs a fresh one.
// Return the new token, or null if the user cancelled.
return await mySignIn(context);
},
),
);
Recommendations #
Show a Cxense recommendations widget via PianoShowRecommendationsParams:
final controller = templates.recommendations();
await controller.show(
event,
context,
PianoShowRecommendationsParams(
renderTemplateUrl: 'auto', // optional, defaults to 'auto'
userId: '<user_id>', // optional
),
);
Display Modes #
show respects the display mode set on the event:
- Modal — opens in a modal popup with an optional close button.
- Inline — loads into a
WebViewyou place in your own layout.
For inline mode, register a controller for the container selector before the
event arrives, and use the returned WebViewController in your widget tree:
final controller = templates.template();
// Register the container selector ahead of time, so the WebViewController
// exists before the show event for it arrives.
late final _templateView = controller.inline('template');
// Use it in your layout.
Container(
// ...
child: WebViewWidget(controller: _templateView),
),
// Later, when the event arrives:
await controller.show(event, context);
The string passed to inline must exactly match the event's
event.eventData.containerSelector — that's how show looks up which
WebViewController to load the template into. If no controller was
registered for that selector, show returns null and nothing is loaded.
Call inline once per container selector you expect to receive events for;
each call returns (or creates) a distinct WebViewController, so a single
controller instance can drive several inline placements at once:
final headerView = controller.inline('#header-template');
final sidebarView = controller.inline('#sidebar-template');
When the owning widget is disposed, release the inline controllers:
@override
void dispose() {
controller.dispose();
super.dispose();
}