UI Components and Integration

SpWML provides several ways to integrate with Flutter, depending on your needs.

SpWML (Basic Widget)

Use this when you want to display a SpWML string immediately as a widget. Since the SpWML class inherits from StatelessWidget, you can use it directly in the widget tree. However, this class cannot control the state. If you want to include buttons or other elements, you will need either SpWMLView or SpWMLBuilder.

// Simple usage
child: SpWML("(h1)Example text")

SpWMLDialog

Makes it easy to create complex, stateful dialogs without defining new classes. This class replaces the content portion of a Flutter alert dialog with SpWML.

If you need a more aesthetically pleasing dialog, you can use SpWMLView and wrap it in a Dialog. Bottom sheets and other elements can be customized in a similar way.

SpWMLBuilder b = SpWMLBuilder(layout);
b.setStateManager(Manager class stored in class variables etc.);
// or b.setManager(the manager class you want to use);
showDialog(
 context: context,
 builder: (context) {
   return SpWMLDialog(
     b,
     const Text('Dialog title'),
     width: 320, // The dialog width
     cancelBtnCallback: (close) {
       close();
     },
     okBtnCallback: (close) {
       close();
     },
   );
 });

Advanced: SpWMLBuilder

The SpWMLBuilder is the core engine. Use it directly for manual manipulations, such as replacing blocks with custom Flutter widgets before building.

SpWMLBuilder b = SpWMLBuilder(layout);

// Embedding Flutter widgets into SpWML "block"
b.replace("target_sid", MyCustomWidget());

// Replace children for multiple child elements like col or row
b.replaceUnderStructure("parent_sid", [Widget1(), Widget2()]);

Widget compiledWidget = b.build(context);

Interacting with Elements from Code

Except for stateless SpWML, elements can be accessed and modified via their sid regardless of the component being used.

// Get element by sid
BtnElement delBtn = builder.getElement("deleteButton") as BtnElement;

// Modify parameters directly
delBtn.setBGColor(Colors.red);
delBtn.textParams.p.isSelectable = true;

Note

Accessing element.params is not recommended as it is for internal use. Please use spwmlParams, elParams, or specific params like textParams.


State Management and Serialization

SpWML manages the state of UI elements (such as text field inputs or switch states) using the simple_managers package.

With SpWMLView (Automatic Management)

In SpWMLView, state management is handled automatically. You don’t need to manually create a StateManager. Use onInit to set initial values and scope.sm in onSetup to access the manager for serialization.

return SpWMLView(
  pathBuilder: (_) => "assets/layout.spwml",
  onInit: (sm) {
    // 1. Pre-set values before UI build
    sm.tfm.setText("user_name", "Taro Yamada");
  },
  onSetup: (context, builder, scope) {
    // 2. Access the manager via scope.sm for serialization
    final manager = scope.sm;
    final Map<String, dynamic> json = manager.toDict(); // Save all states to JSON

    // 3. Set callbacks for buttons
    final btn = builder.getElement("saveBtn") as BtnElement;
    btn.setCallback(() => print("Saved!"));
  },
);

With SpWMLBuilder (Manual Management)

If you are using SpWMLBuilder directly, you must provide a StateManager instance yourself and manage its lifecycle.

// In your State Class
final manager = StateManager();

@override
void dispose() {
  manager.dispose(); // Important: Manually dispose the manager
  super.dispose();
}

@override
Widget build(BuildContext context) {
  SpWMLBuilder b = SpWMLBuilder(layout);
  b.setStateManager(manager); // Link the manager to the builder
  return b.build(context);
}