diff --git a/README.md b/README.md index 2444d24..9235c47 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,38 @@ Add to your `pubspec.yaml` dependencies to `rx_widgets` ## Available Classes +### RxEntry +Creates a `TextField` widget that takes an `RxCommand` as an argument where it takes the input texts and returns the validation message if there is a validation error. + +```Dart + + +RxEntry( + {this.hintText = "", + this.filledColor = Colors.transparent, + this.fieldName, + this.textStream, + this.validationStream, + this.obscureText = false, + this.icon, + this.focusedBorderColor = Colors.transparent, + this.focusedBorderWidth = 0, + this.unfocusedBorderColor = Colors.transparent, + this.unfocusedBorderWidth = 0, + this.borderRadius = 0}); +``` +Example: + ```Dart + RxEntry( + icon: Icons.person, + fieldName: "Username", + validationStream: usernameValidation + textStream: usernameChanged); +``` +Where `usernameChanged` and `usernameValidation` are of type `RxCommand` + ### RxRaisedButton -Creates a RaisedButton that has an rxCommand instead of onPressed. It gets disabled if the command has canExecute:false or when isExecuting:true +Creates a `RaisedButton` that has an rxCommand instead of onPressed. It gets disabled if the command has canExecute:false or when isExecuting:true ```Dart /// an extended `RaisedButton` where the `onPressed` is replaced with `rxCommand` @@ -62,6 +92,46 @@ const RxRaisedButton({ animationDuration: animationDuration, child: child, ); + + /*Title of the entry that would show above the text*/ + final String fieldName; + /** + * `RxCommand` where the input is the text entered, and the output is the validation text + * For exmaple: + *``` + * String username; + * RxCommand usernameChanged; + * MyClass() + * { + * username = ""; + * usernameChanged = RxCommand.createSync((s) + * { + * username = s; + * if (s.isEmpty) + * return "Cannot be empty"; + * if (s.length==3) + * return "Cannot be 3 characters"; + * return ""; + * }); + *``` + */ + final RxCommand onChanged; + + /// To hide the text (mainly used for passwords) + final bool obscureText; + + /// Icon which would be placed to the left of the text + final IconData icon; + + final double focusedBorderWidth; + final Color focusedBorderColor; + final double unfocusedBorderWidth; + final Color unfocusedBorderColor; + final double borderRadius; + final Color filledColor; + + /// The place holder + final String hintText; ``` diff --git a/lib/rx_widgets.dart b/lib/rx_widgets.dart index ae40bfe..0c30f51 100644 --- a/lib/rx_widgets.dart +++ b/lib/rx_widgets.dart @@ -1,5 +1,5 @@ library rx_widgets; - +export 'src/rx_entry.dart'; export 'src/rx_raisedButton.dart'; export 'src/rx_spinner.dart'; export 'src/rx_text.dart'; diff --git a/lib/src/rx_entry.dart b/lib/src/rx_entry.dart new file mode 100644 index 0000000..cacd080 --- /dev/null +++ b/lib/src/rx_entry.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; +import 'package:rx_command/rx_command.dart'; + +///A `TextField` based widget that takes `RxCommand` as input stream and another optional `RxCommand` for validation. +/// ``` +/// RxEntry( +/// icon: Icons.person, +/// fieldName: "Username", +/// validationStream: usernameValidation, +/// textStream: usernameChanged); +/// ``` +/// Where `usernameChanged` and `usernameValidation` are of type `RxCommand` +class RxEntry extends StatelessWidget { + RxEntry( + {this.hintText = "", + this.filledColor = Colors.transparent, + this.fieldName, + this.textStream, + this.validationStream, + this.obscureText = false, + this.icon, + this.focusedBorderColor = Colors.transparent, + this.focusedBorderWidth = 0, + this.unfocusedBorderColor = Colors.transparent, + this.unfocusedBorderWidth = 0, + this.borderRadius = 0}); + @override + Widget build(BuildContext context) { + return StreamBuilder( + stream: validationStream, + initialData: "", + builder: (context, snapshot) { + if (!snapshot.hasData || snapshot.data.isEmpty) + return TextField( + obscureText: obscureText, + onChanged: (s) { + textStream(s); + validationStream(s); + }, + decoration: InputDecoration( + hintText: hintText, + fillColor: filledColor, + filled: true, + labelText: fieldName, + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(borderRadius), + ), + borderSide: (this.focusedBorderColor != Colors.transparent && + this.focusedBorderWidth > 0) + ? BorderSide( + color: this.focusedBorderColor, + width: this.focusedBorderWidth, + ) + : BorderSide.none, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(borderRadius), + ), + borderSide: (this.unfocusedBorderColor != Colors.transparent && + this.unfocusedBorderWidth > 0) + ? BorderSide( + color: this.unfocusedBorderColor, + width: this.unfocusedBorderWidth, + ) + : BorderSide.none, + ), + prefixIcon: icon != null ? Icon(icon) : null, + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(borderRadius), + ), + ), + ), + ); + else + return TextField( + obscureText: obscureText, + onChanged: (s) { + textStream(s); + validationStream(s); + }, + decoration: InputDecoration( + hintText: hintText, + errorText: snapshot.data, + fillColor: filledColor, + filled: true, + labelText: fieldName, + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(borderRadius), + ), + borderSide: (this.focusedBorderColor != Colors.transparent && + this.focusedBorderWidth > 0) + ? BorderSide( + color: this.focusedBorderColor, + width: this.focusedBorderWidth, + ) + : BorderSide.none, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(borderRadius), + ), + borderSide: (this.unfocusedBorderColor != Colors.transparent && + this.unfocusedBorderWidth > 0) + ? BorderSide( + color: this.unfocusedBorderColor, + width: this.unfocusedBorderWidth, + ) + : BorderSide.none, + ), + prefixIcon: icon != null ? Icon(icon) : null, + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(borderRadius), + ), + ), + ), + ); + }, + ); + } + + ///Title of the entry that would show above the text + final String fieldName; + + /** + * `RxCommand` where the input is the text entered, and the output is the validation text. + * If there is not validation then this can be set to null; + * For exmaple: + *``` + * String username; + * RxCommand usernameValidation; + * MyClass() + * { + * + * usernameValidation = RxCommand.createSync((s) + * { + * if (s.isEmpty) + * return "Cannot be empty"; + * if (s.length==3) + * return "Cannot be 3 characters"; + * return ""; + * }); + *``` + */ + final RxCommand validationStream; + + + /// a stream of type `RxCommand` that would take the user's input + final RxCommand textStream; + + + + + /// To hide the text (mainly used for passwords) + final bool obscureText; + + /// Icon which would be placed to the left of the text + final IconData icon; + + final double focusedBorderWidth; + final Color focusedBorderColor; + final double unfocusedBorderWidth; + final Color unfocusedBorderColor; + final double borderRadius; + final Color filledColor; + + /// The place holder + final String hintText; +}