Documentation Index
Fetch the complete documentation index at: https://docs.stac.dev/llms.txt
Use this file to discover all available pages before exploring further.
While Stac provides various built-in actions (navigation, dialogs, network requests, etc.), you may need to create custom actions for your specific use cases. This guide walks you through creating custom StacAction classes that work seamlessly with Stac’s JSON serialization and parser system.
What is a Custom StacAction?
A custom StacAction is a Dart class that:
- Extends the
StacAction base class
- Can be serialized to and deserialized from JSON
- Works with Stac’s action parser system to execute behaviors
- Can be triggered from widgets in your JSON definitions
Custom actions enable you to:
- Integrate third-party services and APIs
- Implement business-specific logic
- Extend Stac’s action functionality beyond built-in actions
- Create reusable behaviors for your application
Prerequisites
Before creating a custom action, ensure you have:
- Dependencies:
stac and json_annotation packages
- Code Generation:
build_runner for generating JSON serialization code
- Parser: A corresponding action parser to execute your action.
Step-by-Step Guide
Step 1: Define Your Action Class
Create a new file (e.g., lib/actions/stac_share_action.dart) and define your action class:
import 'package:json_annotation/json_annotation.dart';
import 'package:stac/stac_core.dart';
part 'stac_share_action.g.dart';
@JsonSerializable()
class StacShareAction extends StacAction {
const StacShareAction({
required this.text,
this.subject,
this.title,
});
final String text;
final String? subject;
final String? title;
@override
String get actionType => 'share';
factory StacShareAction.fromJson(Map<String, dynamic> json) =>
_$StacShareActionFromJson(json);
@override
Map<String, dynamic> toJson() => _$StacShareActionToJson(this);
}
Step 2: Required Components
Every custom StacAction must include:
1. Part File Declaration
part 'stac_share_action.g.dart';
This enables code generation for JSON serialization.
2. JsonSerializable Annotation
For nested actions or complex types, use explicitToJson: true:
@JsonSerializable(explicitToJson: true)
3. Action Type Getter
@override
String get actionType => 'share';
This unique identifier is used in JSON: {"actionType": "share"}.
4. Constructor
const StacShareAction({
required this.text,
this.subject,
});
The base StacAction constructor handles JSON data internally.
5. fromJson Factory Constructor
factory StacShareAction.fromJson(Map<String, dynamic> json) =>
_$StacShareActionFromJson(json);
6. toJson Method
@override
Map<String, dynamic> toJson() => _$StacShareActionToJson(this);
Step 3: Generate Code
Run code generation to create the *.g.dart file:
flutter pub run build_runner build --delete-conflicting-outputs
This generates stac_share_action.g.dart with the serialization logic.
Step 4: Create an Action Parser
To execute your action, create an action parser:
import 'package:flutter/material.dart';
import 'package:stac_framework/stac_framework.dart';
import 'package:share_plus/share_plus.dart';
import 'package:your_app/actions/stac_share_action.dart';
class StacShareActionParser implements StacActionParser<StacShareAction> {
const StacShareActionParser();
@override
String get actionType => 'share';
@override
StacShareAction getModel(Map<String, dynamic> json) =>
StacShareAction.fromJson(json);
@override
FutureOr<dynamic> onCall(BuildContext context, StacShareAction model) async {
return await Share.share(
model.text,
subject: model.subject,
);
}
}
Step 5: Register the Action Parser
Register your action parser during Stac initialization:
void main() async {
await Stac.initialize(
options: defaultStacOptions,
actionParsers: const [
StacShareActionParser(),
],
);
runApp(const MyApp());
}
Advanced Patterns
Using Converters
Similar to widgets, actions can use converters for special types:
DoubleConverter
For double fields that may come as integers in JSON:
import 'package:stac/stac_core.dart';
@JsonSerializable()
class StacCustomAction extends StacAction {
const StacCustomAction({
this.duration,
});
@DoubleConverter()
final double? duration;
@override
String get actionType => 'customAction';
// ... fromJson and toJson
}
Using Custom Actions
In Dart (stac/ folder)
import 'package:stac/stac_core.dart';
import 'package:your_app/actions/stac_share_action.dart';
@StacScreen(screenName: 'article')
StacWidget articleScreen() {
return StacScaffold(
body: StacColumn(
children: [
StacText(data: 'Article Title'),
StacElevatedButton(
onPressed: StacShareAction(
text: 'Check out this article!',
subject: 'Article',
).toJson(),
child: StacText(data: 'Share'),
),
],
),
);
}
After stac build or stac deploy, your generated json looks like this:
{
"type": "elevatedButton",
"onPressed": {
"actionType": "share",
"text": "Check out this article!",
"subject": "Article"
},
"child": {
"type": "text",
"data": "Share"
}
}
Actions are commonly used in widget onPressed, onTap, and other callback properties. For example:
{
"type": "gestureDetector",
"onTap": {
"actionType": "share",
"text": "Shared content"
},
"child": {
"type": "text",
"data": "Tap to share"
}
}