live_cell_extension 0.6.2
live_cell_extension: ^0.6.2 copied to clipboard
Generates cell property accessors for classes annotated with CellExtension from the live_cells package.
import 'package:flutter/material.dart';
import 'package:live_cells/live_cells.dart';
import 'package:live_cells/live_cells_ui.dart';
part 'main.g.dart';
/// A custom class
///
/// The [CellExtension] annotation tells live_cell_extension to generate an
/// extension on `ValueCell<Person>` which provides accessors for the class's
/// properties.
///
/// `mutable: true` tells live_cell_extension to also generated an extension
/// on `MutableCell<Person>` which provides accessors for the class's properties
/// that return `MutableCell`'s.
@CellExtension(mutable: true)
class Person {
final String firstName;
final String lastName;
final int age;
const Person({
required this.firstName,
required this.lastName,
required this.age
});
String get fullName => '$firstName $lastName';
/// This uses the equals function generated by CellExtension.
@override
bool operator ==(Object other) => _$PersonEquals(this, other);
/// This uses the hashCode function generated by CellExtension.
@override
int get hashCode => _$PersonHashCode(this);
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends CellWidget {
@override
Widget build(BuildContext context) {
// A cell to hold the person's details
final person = MutableCell(const Person(
firstName: '',
lastName: '',
age: 25
));
ValueCell.watch(() {
// This is to demonstrate that all observers of person are notified
// when a property changes
print('Person changed: ${person().fullName}');
});
return Scaffold(
appBar: AppBar(
title: const Text('CellExtension Demo'),
),
body: Center(
child: Column(
children: [
Flexible(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Person Details:',
),
const SizedBox(height: 10),
// Notice it is not necessary to wrap the property cells
// in cell(...) or to store them in a local variable.
LiveTextField(
content: person.firstName,
decoration: const InputDecoration(
label: Text('First Name')
),
),
LiveTextField(
content: person.lastName,
decoration: const InputDecoration(
label: Text('Last Name')
),
),
NumberField(
value: person.age,
label: 'Age'
),
const SizedBox(height: 20),
const Text(
'The following uses the cell holding the entire Person, person():',
style: TextStyle(
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 10),
CellWidget.builder((context) => Text('${person().fullName} is ${person().age} years old.')),
const SizedBox(height: 20),
ElevatedButton(
child: const Text('Reset'),
onPressed: () {
person.value = const Person(
firstName: '',
lastName: '',
age: 25
);
},
),
const SizedBox(height: 20),
const Text(
'The following uses the generated accessors:',
style: TextStyle(
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 10),
Row(
mainAxisSize: MainAxisSize.max,
children: [
const Text('person.firstName():'),
const Spacer(),
Text(person.firstName()),
],
),
const SizedBox(height: 5),
Row(
mainAxisSize: MainAxisSize.max,
children: [
const Text('person.lastName():'),
const Spacer(),
Text(person.lastName()),
],
),
const SizedBox(height: 5),
Row(
mainAxisSize: MainAxisSize.max,
children: [
const Text('person.age():'),
const Spacer(),
Text('${person.age()}'),
],
),
const SizedBox(height: 10),
],
),
),
),
),
],
),
),
);
}
}
/// A text field for a number.
///
/// The value of the [value] cell is synchronized with the numeric input that is
/// entered by the user.
class NumberField extends CellWidget {
final String label;
final MutableCell<int> value;
const NumberField({
super.key,
required this.label,
required this.value
});
@override
Widget build(BuildContext context) {
final maybe = value.maybe();
final content = maybe.mutableString();
final error = maybe.error;
return LiveTextField(
content: content,
keyboardType: TextInputType.number,
decoration: InputDecoration(
errorText: error() != null
? 'Not a valid integer'
: null
),
);
}
}