reactive_validator 1.0.0-dev.1 copy "reactive_validator: ^1.0.0-dev.1" to clipboard
reactive_validator: ^1.0.0-dev.1 copied to clipboard

outdated

Type safe validation controller with base validators. Allows to manage validation state manually or validate when reactive value changes.

example/example.dart

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:reactive_validator/reactive_validator.dart';

class ValidationPage extends StatefulWidget {
  @override
  _ValidationPageState createState() => _ValidationPageState();
}

class _ValidationPageState extends State<ValidationPage> {
  final StreamValidationController<_Fields> _controller = SubjectStreamValidationController<_Fields>();
  final StreamController<RegisterState> _stateController = StreamController.broadcast();

  StreamSubscription<RegisterState> _subscription;
  RegisterState _lastValue;

  @override
  void initState() {
    _subscription = _stateController.stream.listen((event) {
      _lastValue = event;
    });

    final now = DateTime.now();

    _controller.attachConnectors([
      StreamValidationConnector<_Fields, String>(
        field: _Fields.EMAIL,
        stream: _stateController.stream.map((state) => state.email).distinct(),
        validator: const AndValidator(const [
          const IsNotNullValidator(),
          const NotEmptyStringValidator(),
          const EmailValidator(),
        ]),
      ),
      StreamValidationConnector<_Fields, String>(
        field: _Fields.PASSWORD,
        stream: _stateController.stream.map((state) => state.password).distinct(),
        validator: const AndValidator(const [
          const IsNotNullValidator(),
          const NotEmptyStringValidator(),
          const MinCharactersValidator(6),
        ]),
      ),
      StreamValidationConnector<_Fields, DateTime>(
        field: _Fields.BIRTHDAY,
        stream: _stateController.stream.map((state) => state.birthday).distinct(),
        validator: AndValidator([
          const IsNotNullValidator(),
          BeforeDateTimeValidator.withMessage(
              DateTime(
                  now.year,
                  now.month,
                  now.day
              ),
              'Date should be in past'
          ),
        ]),
      ),
    ]);

    _stateController.add(RegisterState());

    super.initState();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(
      title: Text('Validation'),
    ),
    body: Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: StreamBuilder<String>(
              stream: _controller.fieldErrorStream(_Fields.EMAIL),
              builder: (context, snapshot) => TextField(
                decoration: InputDecoration(
                  labelText: 'Email',
                  errorText: snapshot.data,
                ),
                onChanged: (value) {
                  _stateController.add(
                      _lastValue.copyWith(
                        email: value,
                      )
                  );
                },
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: StreamBuilder<String>(
              stream: _controller.fieldErrorStream(_Fields.PASSWORD),
              builder: (context, snapshot) => TextField(
                decoration: InputDecoration(
                  labelText: 'Password',
                  errorText: snapshot.data,
                ),
                onChanged: (value) {
                  _stateController.add(
                      _lastValue.copyWith(
                        password: value,
                      )
                  );
                },
              ),
            ),
          ),
          StreamBuilder<String>(
            stream: _controller.fieldErrorStream(_Fields.BIRTHDAY),
            builder: (context, snapshot) => Row(
              children: [
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: InputDecorator(
                      decoration: InputDecoration(
                        errorText: snapshot.data,
                      ),
                      child: Text(_lastValue?.birthday?.toString() ?? 'No date selected'),
                    ),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: IconButton(
                      icon: Icon(Icons.event),
                      onPressed: () async {
                        final dateTime = await showDatePicker(
                          context: context,
                          initialDate: _lastValue?.birthday ?? DateTime.now(),
                          firstDate: DateTime(DateTime.now().year - 2),
                          lastDate: DateTime(DateTime.now().year + 2),
                        );

                        if (dateTime == null) {
                          return;
                        }

                        _stateController.add(
                            _lastValue.copyWith(
                              birthday: dateTime,
                            )
                        );
                      }
                  ),
                ),
              ],
            ),
          ),
          RaisedButton(
              child: Text('Validate'),
              onPressed: () {
                _controller.validate();
              }
          ),
        ],
      ),
    ),
  );

  @override
  void dispose() {
    _subscription.cancel();
    _controller.dispose();
    _stateController.close();

    super.dispose();
  }
}

enum _Fields {
  EMAIL,
  PASSWORD,
  BIRTHDAY,
}

class RegisterState {
  final String email;
  final String password;
  final DateTime birthday;

  RegisterState({this.email, this.password, this.birthday});

  RegisterState copyWith({
    String email,
    String password,
    DateTime birthday,
  }) => RegisterState(
    email: email ?? this.email,
    password: password ?? this.password,
    birthday: birthday ?? this.birthday,
  );
}
7
likes
0
pub points
60%
popularity

Publisher

unverified uploader

Type safe validation controller with base validators. Allows to manage validation state manually or validate when reactive value changes.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

email_validator, flutter, rxdart

More

Packages that depend on reactive_validator