0 purchases
prop commands
Property and Commands for ChangeNotifier #
The package contains the following decorating classes: Property<T>, Command, ParameterizedCommand<T>, AsyncCommand, ParameterizedAsyncCommand<T>. These classes can be useful when creating viewmodels based on classes extending ChangeNotifier.
Example #1 #
Properties and commands are defined in the viewmodel class class FirstPageNotifier extends ChangeNotifier.
Property #
To store the counter value
late final outputProperty = Property<int>(
initialValue: 0,
notifyListeners: notifyListeners,
);
copied to clipboard
The initial value of the property is set and the method notifyListeners() is called if
the value of this property changes.
In the build(BuildContext context) method of the FirstPage extends StatelessWidget class
we get a tracked reference to the property value
final output =
FirstPageInheritedNotifier.watchNotifier(context).outputProperty.value;
copied to clipboard
the output of the value is as follows
Text(
output.toString(),
style: Theme.of(context).textTheme.headlineLarge,
),
copied to clipboard
Commands #
Two commands have been created for increment and decrement of the counter
late final incrementCommand = Command(
action: () => outputProperty.value += 1,
canAction: () => outputProperty.value < 3,
);
late final decrementCommand = Command(
action: () => outputProperty.value -= 1,
canAction: () => outputProperty.value > 0,
);
copied to clipboard
Methods that change the value of the counter property are passed as arguments for the action parameter.
Methods that limit the range of counter values are passed as arguments for the canAction parameter, which restricts the availability of the command to execute.
In the FirstPage class in the build(BuildContext context) method getting links to commands
final incrementCommand =
FirstPageInheritedNotifier.readNotifier(context).incrementCommand;
final decrementCommand =
FirstPageInheritedNotifier.readNotifier(context).decrementCommand;
copied to clipboard
Using commands to operate buttons
ElevatedButton(
onPressed: decrementCommand.canExecute()
? decrementCommand.execute
: null,
child: const Icon(Icons.exposure_minus_1),
),
copied to clipboard
and
ElevatedButton(
onPressed: incrementCommand.canExecute()
? incrementCommand.execute
: null,
child: const Icon(Icons.plus_one),
),
copied to clipboard
You can see that in the method of the onPressed parameter the possibility of executing the command is checked which affects the availability of the button for clicking.
Example #2 #
The properties and command are defined in the viewmodel class SecondPageNotifier extends ChangeNotifier.
Property #
To display the counter value, one property is defined, which is set only by its initial value.
final outputProperty = Property<int>(initialValue: 0);
copied to clipboard
In the SecondPage class in the build(BuildContext context) method getting a tracked reference to the property value
final output =
SecondPageInheritedNotifier.watchNotifier(context).outputProperty.value;
copied to clipboard
for displaying the property value
Text(
output.toString(),
style: Theme.of(context).textTheme.headlineLarge,
),
copied to clipboard
Command #
One common parameterized command is defined for the buttons,
which, when called for execution, takes an int value as an argument.
late final changeCommand = ParameterizedCommand<int>(
action: (value) => outputProperty.value += value,
notifyListeners: notifyListeners,
);
copied to clipboard
When executing the command method, notifyListeners() is called.
In the SecondPage class in the build(BuildContext context) method we get a link to the command
final command =
SecondPageInheritedNotifier.readNotifier(context).changeCommand;
copied to clipboard
Using the command for buttons looks like this
ElevatedButton(
onPressed: () => command(-1),
child: Text(
'-1',
style: Theme.of(context).textTheme.titleLarge,
),
),
...
ElevatedButton(
onPressed: () => command(3),
child: Text(
'3',
style: Theme.of(context).textTheme.titleLarge,
),
),
copied to clipboard
Example #3 #
In the viewmodel class ThirdPageNotifier extends ChangeNotifier, three properties and a command are defined.
Properties #
The CheckboxListTile property is set with the notifyListeners() call.
late final isEnabledProperty = Property<bool>(
initialValue: false,
notifyListeners: notifyListeners,
);
copied to clipboard
Next, in _Third Page State we get a tracked reference to this property
final isEnabledProperty =
ThirdPageInheritedNotifier.watchNotifier(context).isEnabledProperty;
copied to clipboard
and we use it this way
CheckboxListTile(
title: const Text('enable the input line'),
controlAffinity: ListTileControlAffinity.platform,
contentPadding: const EdgeInsets.all(50),
value: isEnabledProperty.value,
onChanged: (value) {
isEnabledProperty.value = value!;
},
),
copied to clipboard
A property is set for TextField with a call to notifyListeners() and verification rules.
late final inputProperty = Property<String>(
initialValue: '',
notifyListeners: notifyListeners,
verificationRules: <String, bool Function(String)>{
'The value cannot be an empty string': (value) => value.isEmpty,
'The length of the string cannot be less than 3 characters': (value) =>
value.length < 3,
},
);
copied to clipboard
For the verification rule, a text message for the user is specified as the key,
and the method returning true is specified as the value.
In the InputTextWidget we get references to the properties
final isEnabledProperty =
ThirdPageInheritedNotifier.watchNotifier(context).isEnabledProperty;
final inputProperty =
ThirdPageInheritedNotifier.readNotifier(context).inputProperty;
copied to clipboard
and we use it this way
TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: 'Enter the Value',
errorText: inputProperty.hasErrors ? inputProperty.errors[0] : null,
),
enabled: isEnabledProperty.value,
controller: controller,
onChanged: (text) {
inputProperty.value = text;
},
),
copied to clipboard
In this line errorText: inputProperty.hasErrors ? inputProperty.errors[0] : null, the
logic of displaying error messages to the user when entering data is defined.
The accessibility of the TextField for input is tied to the value of the CheckBoxListTile via
the isEnabledProperty property in this line enabled: isEnabledProperty.value,.
The inputProperty property updates its value in the method defined for onChanged.
A simple property is used to output the result
final outputProperty = Property<String>(initialValue: '');.
Command #
The example uses one asynchronous command for the button
late final submitCommand = AsyncCommand(
action: () async {
await Future.delayed(const Duration(milliseconds: 100));
outputProperty.value = inputProperty.value;
inputProperty.value = '';
isEnabledProperty.value = false;
},
canAction: () => inputProperty.hasErrors == false,
notifyListeners: notifyListeners,
);
copied to clipboard
The availability of the button depends on the presence of errors when entering using
the parameter canAction: () => inputProperty.hasErrors == false,.
When executing the command method, notifyListeners() is called.
In _ThirdPageState we get a link to the command
final submitCommand =
ThirdPageInheritedNotifier.readNotifier(context).submitCommand;
copied to clipboard
and we use the command for the button in this way.
ElevatedButton(
onPressed: submitCommand.canExecute()
? (() async {
await submitCommand.execute();
controller.clear();
})
: null,
child: const Icon(Icons.done),
),
copied to clipboard
Example #4 #
One property and three commands are defined in the FourthPageNotifier extends ChangeNotifier viewmodel class.
Property #
A property has been created to display the list.
final peopleProperty = Property<List<Person>>(
initialValue: <Person>[],
);
copied to clipboard
In the PeopleListViewWidget we get a tracked reference to the property.
final people =
FourthPageInheritedNotifier.watchNotifier(context).peopleProperty.value;
copied to clipboard
Displaying a collection of people using ListView.builder() and ListTile.
ListView.builder(
itemCount: people.length,
itemBuilder: (context, index) {
final person = people[index];
return ListTile(
onTap: () async {...},
title: Text(person.fullName),
subtitle: Text('ID: ${person.id}'),
trailing: TextButton(...),
);
},
),
copied to clipboard
Commands #
To implement CRUD operations on a collection of people , three parameterized asynchronous commands have been created: addCommand, removeCommand, updateCommand.
Example on addCommand.
late final addCommand = ParameterizedAsyncCommand<List<String>>(
action: (value) async {
await _db.create(names: value);
peopleProperty.value = await _db.getPeople();
},
notifyListeners: notifyListeners,
);
copied to clipboard
In Composerwidget in the Widget build(BuildContext context) method we get a link
to the command.
final command =
FourthPageInheritedNotifier.readNotifier(context).addCommand;
copied to clipboard
We use the command in this way
TextButton(
onPressed: () async {
final names = <String>[
firstNameController.text,
lastNameController.text,
];
await command(names);
firstNameController.clear();
lastNameController.clear();
},
child: Text(
'Add to list',
style: Theme.of(context).textTheme.titleMedium,
))
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.