Skip to content

Validation Chain Api for TextFormField in Flutter or Backend application made with Dart.

License

Notifications You must be signed in to change notification settings

Pr47h4m/validation_chain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

19 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Validation Chain

ValidationChain, MapValidator, MapSanitizer, Sanitizable interface.

ValidationChain api to use with TextFormField in Flutter or Backend applicaitons made with Dart.

ValidationChain is an Array of Validator functions that can be used to validate the content of TextFormField in Flutter.

It is done by passing ValidationChain to the validator property of TextFormField. So when we call validate method on the current state of the form key, the chain of validators is executed sequentially and returns the first validation error (if present).

That helps the developer to keep source code organized by separating validation logic from UI.

SanitizationChain api to use with TextFormField in Flutter or Backend applicaitons made with Dart.

SanitizationChain is an Array of Sanitizer functions that can be used to sanitize the content of TextFormField in Flutter.

It is done by passing SanitizationChain to the onSaved property of TextFormField. So when we call the save method on the current state of the form key, the chain of sanitizers is executed sequentially and returns the final sanitized value (which can also be used to update the content of TextFormField by using _controller.text = sanitizedValue)

That helps the developer to sanitize all the values before passing them to the backend, which reduces the chance of errors due to unsanitized data

MapValidator / MapSanitizer api to validate/sanitize Map<dynamic, dynamic>.

MapValidator and MapSanitizer are the best benefits provided by the package to validate/sanitize Map<dynamic, dynamic>. That is very useful when we develop server-side / CLI-based apps using dart.

Usage

ValidationChain with TextFormField in Flutter

Example
import 'package:flutter/material.dart';
import 'package:validation_chain/validation_chain.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  App({super.key});

  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Validation Chain Example'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Form(
              key: _formKey,
              child: TextFormField(
                decoration: const InputDecoration(labelText: 'Name'),
                validator: ValidationChain(
                  [compulsory, tooShort, tooLong],
                ).validate,
              ),
            ),
            const SizedBox(height: 32),
            ElevatedButton(
              child: const Text('Validate'),
              onPressed: () {
                _formKey.currentState!.validate();
              },
            ),
          ],
        ),
      ),
    );
  }

  /* -----Utility functions----- */

  String? compulsory(String? value) {
    return (value?.isEmpty ?? true) ? 'Required' : null;
  }

  String? tooShort(String? value) {
    return value != null && value.length < 5 ? 'Too Short' : null;
  }

  String? tooLong(String? value) {
    return value != null && value.length > 10 ? 'Too Long' : null;
  }
}

ValidationChain with Dart CLI based apps

Example
import 'package:validation_chain/validation_chain.dart';

void main() {
  const validationChain = ValidationChain(
    [compulsory, tooShort, tooLong],
  );

  validationChain.validate('');            // 'Required'
  validationChain.validate('Hey');         // 'Too Short'
  validationChain.validate('Hello');       // null
  validationChain.validate('Hello World'); // 'Too Long'
}

/* -----Utility functions----- */

String? compulsory(String? value) {
  return (value?.isEmpty ?? true) ? 'Required' : null;
}

String? tooShort(String? value) {
  return value != null && value.length < 5 ? 'Too Short' : null;
}

String? tooLong(String? value) {
  return value != null && value.length > 10 ? 'Too Long' : null;
}

SanitizationChain with TextFormField in Flutter

Example
import 'package:flutter/material.dart';
import 'package:validation_chain/validation_chain.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  App({super.key});

  final _formKey = GlobalKey<FormState>();
  final _email = TextEditingController(text: '    [email protected]    ');

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Sanitization Chain Example'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Form(
              key: _formKey,
              child: TextFormField(
                controller: _email,
                decoration: const InputDecoration(labelText: 'Email'),
                onSaved: (value) {
                  _email.text = SanitizerChain(
                        [trim, lowerCase],
                      ).sanitize(value) ??
                      '';
                },
              ),
            ),
            const SizedBox(height: 32),
            ElevatedButton(
              child: const Text('Sanitize'),
              onPressed: () {
                _formKey.currentState!.save();
              },
            ),
          ],
        ),
      ),
    );
  }

  /* -----Utility functions----- */

  String? trim(String? value) {
    return value?.trim();
  }

  String? lowerCase(String? value) {
    return value?.toLowerCase();
  }
}

SanitizationChain with Dart CLI based apps

Example
import 'package:validation_chain/validation_chain.dart';

void main() {
  const sanitizationChain = SanitizationChain([
    trim,
    lowerCase,
  ]);

  sanitizationChain.sanitize('   [email protected]   '); // '[email protected]'
}

/* -----Utility functions----- */

String? trim(String? value) {
  return value?.trim();
}

String? lowerCase(String? value) {
  return value?.toLowerCase();
}

MapSanitizer

Example
import 'package:validation_chain/validation_chain.dart';

void main() {
  final payload = <String, dynamic>{
    'email': '   [email protected]   ',
    'password': ' 123456 ',
  };

  final mapSanitizers = <dynamic, List<Sanitizer>>{
    'email': [trim, lowerCase],
    'password': [trim],
  };

  MapSanitizer(mapSanitizers).sanitize(
    payload,
  ); // {'email': '[email protected]', 'password': '123456'}
}

/* -----Utility functions----- */

String? trim(String? value) {
  return value?.trim();
}

String? lowerCase(String? value) {
  return value?.toLowerCase();
}

MapValidator

Example
import 'package:validation_chain/validation_chain.dart';

void main() {
  final payload = <String, dynamic>{
    'email': null,
    'password': '1234',
  };

  final mapValidators = <dynamic, List<Validator>>{
    'email': [compulsory],
    'password': [compulsory, tooShort],
  };

  MapValidator(mapValidators).validate(payload);    // Required
  MapValidator(mapValidators).rawValidate(payload); // [{'field': 'email', 'errors': ['Required']}, {'field': 'password', 'errors': ['Too Short']}]
}

/* -----Utility functions----- */

String? compulsory(String? value) {
  return (value?.isEmpty ?? true) ? 'Required' : null;
}

String? tooShort(String? value) {
  return value != null && value.length < 5 ? 'Too Short' : null;
}

String? tooLong(String? value) {
  return value != null && value.length > 10 ? 'Too Long' : null;
}

Using ValidationChain, MapSanitizer & MapValidator together πŸš€

Example
import 'package:validation_chain/validation_chain.dart';

void main() {
  // example of using ValidationChain
  const validationChain = ValidationChain([
    compulsory,
    tooShort,
    tooLong,
  ]);

  validationChain.validate('');            // 'Required'
  validationChain.validate('Hey');         // 'Too Short'
  validationChain.validate('Hello');       // null
  validationChain.validate('Hello World'); // 'Too Long'

  // example of using MapSanitizer & MapValidator & ValidationChain
  final payload = <String, dynamic>{
    'email': '   [email protected]   ',
    'password': ' 123456 ',
  };

  final mapSanitizers = <dynamic, List<Sanitizer>>{
    'email': [trim, lowerCase],
    'password': [trim],
  };

  MapSanitizer(mapSanitizers).sanitize(
    payload,
  ); // {'email': '[email protected]', 'password': '123456'}

  final mapValidators = <dynamic, List<Validator>>{
    'email': [compulsory],
    'password': [validationChain.validate], // you can also pass pre created ValidationChain like this, Note: ValidationChain.validate returns the first error in the chain and does not test next validators in the chain
  };

  MapValidator(mapValidators).validate(payload); // null
  payload['email'] = null;                       // intentionally making email null
  MapValidator(mapValidators).validate(payload); // Required
  payload['password'] = '1234';
  MapValidator(mapValidators).rawValidate(payload)?.map((e) => e.toJson()); // ({'field': 'email','errors': ['Required']}, {'field': 'password', 'errors': ['Too Short']})
}

/* -----Utility functions----- */

String? compulsory(String? value) {
  return (value?.isEmpty ?? true) ? 'Required' : null;
}

String? tooShort(String? value) {
  return value != null && value.length < 5 ? 'Too Short' : null;
}

String? tooLong(String? value) {
  return value != null && value.length > 10 ? 'Too Long' : null;
}

String? trim(String? value) {
  return value?.trim();
}

String? lowerCase(String? value) {
  return value?.toLowerCase();
}

Maintainers

pr47h4m

About

Validation Chain Api for TextFormField in Flutter or Backend application made with Dart.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages