validate: update README for MapField
This commit is contained in:
parent
1ed5d20ad6
commit
5b3472c677
3 changed files with 48 additions and 15 deletions
|
@ -28,15 +28,30 @@ its usage in `package:test`):
|
|||
var positiveNumberField = IntField('pos_num').match([isPositive]);
|
||||
```
|
||||
|
||||
A `MapField` can embed a `Form` (forms covered below), and when combined with
|
||||
`Field.deserialize`, can be used to deserialize structured data as a body field:
|
||||
|
||||
```dart
|
||||
app.post('/map_field', (req, res) async {
|
||||
var form = Form(fields: [
|
||||
MapField('todo', todoForm).deserialize(Todo.fromMap),
|
||||
]);
|
||||
|
||||
var data = await form.validate(req);
|
||||
print(data['todo'] is Todo);
|
||||
});
|
||||
```
|
||||
|
||||
There are several included field types:
|
||||
* `TextField`
|
||||
* `BoolField`
|
||||
* `NumField`
|
||||
* `DoubleField`
|
||||
* `IntField`
|
||||
* `DateTimeField`
|
||||
* `FileField`
|
||||
* `ImageField`
|
||||
* `TextField` - Standard text input.
|
||||
* `BoolField` - Checks if a field is present; used for checkboxes.
|
||||
* `NumField` - Base class that parses input as a number.
|
||||
* `DoubleField` - Specialization of `NumField` for doubles.
|
||||
* `IntField` - Specialization of `NumField` for integers.
|
||||
* `DateTimeField` - Parses an input as an ISO-8601 date.
|
||||
* `FileField` - Validates a file in `req.uploadedFiles`.
|
||||
* `ImageField` - Uses `package:image` to decode an `UploadedFile` into an image.
|
||||
* `MapField` - Validates a Map using a Form.
|
||||
|
||||
# Forms
|
||||
The `Form` class lets you combine `Field` instances, and decode
|
||||
|
@ -55,9 +70,15 @@ var todo = await todoForm.deserialize(req, TodoSerializer.fromMap);
|
|||
// Same as above, but with a Codec<Todo, Map> (i.e. via `angel_serialize`).
|
||||
var todo = await todoForm.decode(req, todoSerializer);
|
||||
|
||||
// Same as above, but returns the plain Map without any deserialization.
|
||||
var todoMap = await todoForm.validate(req);
|
||||
|
||||
// Lower-level functionality, typically not called directly.
|
||||
// Use it if you want to handle validation errors directly, without
|
||||
// throwing exceptions.
|
||||
var result = await todoForm.read(req);
|
||||
print(result.isSuccess);
|
||||
print(result.errors.length);
|
||||
|
||||
@serializable
|
||||
class _Todo {
|
||||
|
|
|
@ -73,12 +73,17 @@ Future<void> main() async {
|
|||
''');
|
||||
});
|
||||
|
||||
app.post('/b', (req, res) async {
|
||||
// You can use a [MapField] to embed one [Form] with another.
|
||||
// In this example, we embed the [todoForm], but also call `.deserialize`,
|
||||
// so that the final value we see is a [Todo] instance, rather than a [Map].
|
||||
app.post('/map_field', (req, res) async {
|
||||
var form = Form(fields: [
|
||||
MapField('todo', todoForm),
|
||||
MapField('todo', todoForm).deserialize(Todo.fromMap),
|
||||
]);
|
||||
var data = await form.read(req);
|
||||
return data;
|
||||
var data = await form.validate(req);
|
||||
var b = StringBuffer();
|
||||
b.write(data);
|
||||
return b.toString();
|
||||
});
|
||||
|
||||
app.fallback((req, res) => throw AngelHttpException.notFound());
|
||||
|
@ -103,4 +108,7 @@ class Todo {
|
|||
static Todo fromMap(Map map) {
|
||||
return Todo(map['text'] as String, map['is_complete'] as bool);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'Todo($text, $isComplete)';
|
||||
}
|
||||
|
|
|
@ -115,7 +115,9 @@ class _MatchedField<T> extends Field<T> {
|
|||
Future<FieldReadResult<T>> read(
|
||||
Map<String, dynamic> fields, Iterable<UploadedFile> files) async {
|
||||
var result = await inner.read(fields, files);
|
||||
if (!result.isSuccess) {
|
||||
if (result == null) {
|
||||
return null;
|
||||
} else if (!result.isSuccess) {
|
||||
return result;
|
||||
} else {
|
||||
var errors = <String>[];
|
||||
|
@ -149,7 +151,9 @@ class _DeserializeField<T, U> extends Field<U> {
|
|||
FutureOr<FieldReadResult<U>> read(
|
||||
Map<String, dynamic> fields, Iterable<UploadedFile> files) async {
|
||||
var result = await inner.read(fields, files);
|
||||
if (!result.isSuccess) {
|
||||
if (result == null) {
|
||||
return null;
|
||||
} else if (!result.isSuccess) {
|
||||
return FieldReadResult.failure(result.errors);
|
||||
} else {
|
||||
return FieldReadResult.success(await converter(result.value));
|
||||
|
|
Loading…
Reference in a new issue