Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to validate on unfocus? #298

Open
woellij opened this issue Apr 6, 2022 · 4 comments
Open

How to validate on unfocus? #298

woellij opened this issue Apr 6, 2022 · 4 comments

Comments

@woellij
Copy link

woellij commented Apr 6, 2022

I'm trying to validate on unfocus, but calling SingleFieldBloc.validate does not emit a new state. Also after input change, a state is emitted, saying it is not dirty. Of course autoValidate is deactivated, but that's the whole point (with it on the validation works)

How can i manually call validate on SingleFieldBlocs and have the error displayed in the TextFieldBlocBuilder?

I've been banging my head against this for hours now ...

the implementation of validate seems to be completely besides the point, what the method-name is conveying ...

@saawhitelife
Copy link

saawhitelife commented May 21, 2022

You may mind this example:

import 'dart:async';

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(),
      home: BlocProvider<MyFormBloc>(
        create: (_) => MyFormBloc(),
        child: const MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final emailFocusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    emailFocusNode.addListener(() {
      if (emailFocusNode.hasFocus) {
        formBloc.removeEmailValidators();
      } else {
        formBloc.addEmailValidators();
      }
    });
  }

  MyFormBloc get formBloc => context.read<MyFormBloc>();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).unfocus();
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextFieldBlocBuilder(
                obscureText: false,
                focusNode: emailFocusNode,
                textFieldBloc: formBloc.emailFieldBloc,
                suffixButton: SuffixButton.obscureText,
                decoration: const InputDecoration(
                  labelText: 'TextFieldBlocBuilder',
                  prefixIcon: Icon(Icons.text_fields),
                  errorStyle: TextStyle(color: Colors.red),
                  border: OutlineInputBorder(),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    emailFocusNode.dispose();
    super.dispose();
  }
}

class MyFormBloc extends FormBloc {
  MyFormBloc() {
    addFieldBloc(fieldBloc: emailFieldBloc);
  }

  final emailValidators = [
    (text) => 'error here',
  ];
  final emailFieldBloc = TextFieldBloc();

  void addEmailValidators() {
    emailFieldBloc.updateValidators(emailValidators);
  }

  void removeEmailValidators() {
    emailFieldBloc.updateValidators([]);
  }

  @override
  void submit() {
    addEmailValidators();
    super.submit();
  }

  @override
  FutureOr<void> onSubmitting() {
    throw UnimplementedError();
  }
}

@woellij
Copy link
Author

woellij commented May 21, 2022

Hi @saawhitelife ,

thanks for getting back to me.
I had this on my plate for a while and while trying to implement it i faced a different issue where with the docker built page, the validation stopped working alltogether (maybe something to do with different pub versions)

Because of that i switched over to reactive_forms (https://pub.dev/packages/reactive_forms) which has the notion of only validating "touched" fields by default. Of course without the utilities of form_bloc.

@otto-dev
Copy link

otto-dev commented May 23, 2022

I am also interested in this. Having fields light up in red once the user starts typing is too agressive.

While not the same, as an alternative workaround, you can call field.updateValidators(...) on the submit button press, adding all your validators, to only validate once the user clicks "submit".

@ingmferrer
Copy link

My proposal: #331

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants