Taniket
Taniket

Reputation: 21

Custom Error Message Widget in TextFields - Flutter

I am trying to create a custom Input widget with custom error message styling. Final Design - Final Design

So far I have updated input with help for making a custom wrapper which add border and padding -

    return Padding(
      padding: const EdgeInsets.only(bottom: 15.0),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(
            color: colors.grey,
            width: 2,
          ),
          borderRadius: BorderRadius.circular(2),
        ),
        padding: const EdgeInsets.symmetric(horizontal: 15.0),
        height: 56.0,
        child: child,
      ),
    );
  }

And code for inputs -

InputWrap(
  child: FormBuilderTextField(
    style: InputFieldStyle.normalTextStyle,
    obscureText: true,
    maxLines: 1,
    decoration: const InputDecoration(
      labelText: 'Password*',
    ),
    validators: <FormFieldValidator>[
      FormBuilderValidators.required(),
    ],
    attribute: 'lastName',
  ),
),

Styles for inputs

inputDecorationTheme: const InputDecorationTheme(
      labelStyle: TextStyle(
        color: Colors.BLUE_PRIMARY,
        fontSize: 14,
        fontWeight: FontWeight.normal,
      ),
      errorStyle: TextStyle(
        color: Colors.BLUE_LIGHT,
        fontSize: 12,
        backgroundColor: Colors.PINK_ERROR_BACKGROUND,
      ),
      border: InputBorder.none,
      focusedBorder: InputBorder.none,
      enabledBorder: InputBorder.none,
      disabledBorder: InputBorder.none,
      isDense: true,
    ),

But now I cant seem to find how I can target and style error bar. Current Progress

UPDATE - SOLVED

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

class CustomTextField extends StatelessWidget {
  const CustomTextField({
    Key key,
    this.attribute,
    this.initialValue,
    this.labelText,
    this.hintText,
    this.suffix,
    this.readOnly = false,
    this.trimOnSave = true,
    this.validatorsList = const <String Function(dynamic)>[],
  }) : super(key: key);

  final String attribute;
  final String initialValue;
  final String labelText;
  final String hintText;
  final Widget suffix;
  final bool readOnly;
  final bool trimOnSave;
  final List<String Function(dynamic)> validatorsList;

  @override
  Widget build(BuildContext context) {
    return FormBuilderCustomField<String>(
      attribute: attribute,
      validators: validatorsList,
      valueTransformer: (dynamic value) {
        // Trim values before save
        return trimOnSave ? value.toString().trim() : value;
      },
      formField: FormField<String>(
        enabled: true,
        initialValue: initialValue,
        builder: (FormFieldState<String> field) {
          return InputWrap(
            child: TextFormField(
              readOnly: readOnly,
              style: InputFieldStyle.normalTextStyle,
              decoration: InputFieldStyle.inputFieldStyle(
                labelText: labelText,
                hintText: hintText,
                suffix: suffix,
              ),
              onChanged: (String data) {
                field.didChange(data);
              },
            ),
            // Show Error Widget below input field if error exist
            hasError: field.hasError,
            errorText: field.errorText,
          );
        },
      ),
    );
  }
}

Upvotes: 2

Views: 6802

Answers (1)

Shubham Gupta
Shubham Gupta

Reputation: 1997

I would suggest you use FormField for this design

FormField<String>(
  builder: (FormFieldState<String> state) {
    return Column(
      children: <Widget>[
       //Your custom text field
       Offstage(
         offstage:!state.hasError,
         child: //your custom error widget
       ),
     ],
   ), 
 ),

You can check this medium story for more details.Here is another great video on the same topic from Flutter Europe

Hope this helps!

Upvotes: 3

Related Questions