A.A
A.A

Reputation: 4101

Flutter force reformat input

By setting _mytexteditingcontroller.value , We can update value of TextField, But inputFormatters is not running

How can I force inputFormatters to reformat value?

Here is a minimal example , I use LengthLimitingTextInputFormatter(3) to limit length of input, by running _controller.text = '12345678' I want to tell flutter to reformat input again

CONSIDER THAT IT IS A MININAL EXAMPLE, DONT TELL ME USE SUBSTRING TO FIX IT

/// Flutter code sample for TextField

// This sample shows how to get a value from a TextField via the [onSubmitted]
// callback.

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

void main() => runApp(MyApp());

/// This is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  TextEditingController _controller;

  void initState() {
    super.initState();
    _controller = TextEditingController();
  }

  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            RaisedButton(
                child: Text('Set Text'),
                onPressed: () {
                  _controller.text = '12345678';
                }),
            TextField(
              controller: _controller,
              inputFormatters: [
                LengthLimitingTextInputFormatter(3),
              ],
              onSubmitted: (String value) async {
                await showDialog<void>(
                  context: context,
                  builder: (BuildContext context) {
                    return AlertDialog(
                      title: const Text('Thanks!'),
                      content: Text('You typed "$value".'),
                      actions: <Widget>[
                        FlatButton(
                          onPressed: () {
                            Navigator.pop(context);
                          },
                          child: const Text('OK'),
                        ),
                      ],
                    );
                  },
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

Upvotes: 4

Views: 744

Answers (1)

bluenile
bluenile

Reputation: 6029

As mentioned above this is a currently open known issue https://github.com/flutter/flutter/issues/30369. However you may try using an extension on TextInputFormatter to achieve a similar result.

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

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  TextEditingController _controller;

  void initState() {
    super.initState();
    _controller = TextEditingController();
  }

  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            RaisedButton(
                child: Text('3 Length Limit'),
                onPressed: () {
                  _controller.text = LengthLimitingTextInputFormatter(3).format('12345678');
                }),
            RaisedButton(
                child: Text('Upper case'),
                onPressed: () {
                  _controller.text = UpperCaseTextFormatter().format('upper');
                }),
           RaisedButton(
                child: Text('Length Limit & Upper chained'),
                onPressed: () {
                  _controller.text = LengthLimitingTextInputFormatter(3).format(UpperCaseTextFormatter().format('upper'));
                }),
                        
            TextField(
              controller: _controller,
              inputFormatters: [
                LengthLimitingTextInputFormatter(3),
                UpperCaseTextFormatter(),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

extension on TextInputFormatter {
    String format(String text) {
        return formatEditUpdate(
            const TextEditingValue(),
            TextEditingValue(
                text: text,
                selection: TextSelection(
          extentOffset: text.length,
                    baseOffset: text.length,
                ),
            ),
        ).text;
    }
}

class UpperCaseTextFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    return TextEditingValue(
      text: newValue.text?.toUpperCase(),
      selection: newValue.selection,
    );
  }
}

Upvotes: 3

Related Questions