Isaque Neves
Isaque Neves

Reputation: 69

How to make a TextInputFormatter Mask for IpAddress in flutter

I am trying to make a TextInputFormatter Mask for IpAddress in flutter

What I am trying to do :

import 'package:flutter/services.dart';

class IpAddressInputFormatter extends TextInputFormatter {
  String separator = '-';

  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    if (newValue.text.length > 0) {
      if (newValue.text.length > oldValue.text.length) {
        String lastEnteredChar = newValue.text.substring(newValue.text.length - 1);
        var value = newValue.text;
        if (lastEnteredChar == separator) {
          if (RegExp(separator).allMatches(newValue.text).length > 3) {
            return oldValue;
          }
          if (newValue.text.length > 9) {
            return oldValue;
          }
          return TextEditingValue(
            text: '$value',
            selection: TextSelection.collapsed(
              offset: value.length,
            ),
          );
        }
        if (!_isNumeric(lastEnteredChar)) return oldValue;
        if (_isNumeric(newValue.text.split(separator).last) && newValue.text.split(separator).last.length == 3) {
          if (newValue.text.length < 16 && newValue.text.split(separator).last.length <= 3) {
            var s = '$separator';
            s = newValue.text.length == 15 ? '' : s;
            s = RegExp(separator).allMatches(newValue.text).length > 2 ? '' : s;
            value = '${newValue.text}$s';
          } else if (RegExp(separator).allMatches(newValue.text).length > 2) {
            return oldValue;
          } else {
            return oldValue;
          }
        } else if (newValue.text.length > 15) {
          return oldValue;
        } else if (RegExp(separator).allMatches(newValue.text).length == 3 &&
            newValue.text.split(separator).last.length > 3) {
          return oldValue;
        }
        return TextEditingValue(
          text: '$value',
          selection: TextSelection.collapsed(
            offset: value.length,
          ),
        );
      }
    }
    return newValue;
  }

  bool _isNumeric(String s) {
    if (s == null) return false;
    return double.tryParse(s) != null;
  }
}

I expect the user to be able to enter 55.55.55.55 | 1.1.1.1 | 1.10.100.4 | etc

Is there a easy way to make an input text fiel for Ip Addresses ?

this code works for some scenarios but not for all ip scenarios, it works well for 10-10-10-10 111-111-111-111 192-168-133-13 1-1-1-1 1-10-10-1 but fails from time to time for 10-100-10-1

Upvotes: 0

Views: 2826

Answers (1)

X12-F1
X12-F1

Reputation: 71

Surely it can be improved but it works for me like this.

inputFormatters: [
              MyInputFormatters.ipAddressInputFilter(),
              LengthLimitingTextInputFormatter(15),
              IpAddressInputFormatter()
            ],

MyInputFormatters.class

class MyInputFormatters {
    static TextInputFormatter ipAddressInputFilter() {
        return FilteringTextInputFormatter.allow(RegExp("[0-9.]"));
    }
}

IpAddressInputFormatter.class

class IpAddressInputFormatter extends TextInputFormatter {
@override
  TextEditingValue formatEditUpdate(
  TextEditingValue oldValue, TextEditingValue newValue) {
  var text = newValue.text;

  if (newValue.selection.baseOffset == 0) {
    return newValue;
  }

  int dotCounter = 0;
  var buffer = StringBuffer();
  String ipField = "";

  for (int i = 0; i < text.length; i++) {
    if (dotCounter < 4) {
      if (text[i] != ".") {
        ipField += text[i];
        if (ipField.length < 3) {
          buffer.write(text[i]);
        } else if (ipField.length == 3) {
          if (int.parse(ipField) <= 255) {
            buffer.write(text[i]);
          } else {
            if (dotCounter < 3) {
              buffer.write(".");
              dotCounter++;
              buffer.write(text[i]);
              ipField = text[i];
            }
          }
        } else if (ipField.length == 4) {
          if (dotCounter < 3) {
            buffer.write(".");
            dotCounter++;
            buffer.write(text[i]);
            ipField = text[i];
          }
        }
      } else {
        if (dotCounter < 3) {
          buffer.write(".");
          dotCounter++;
          ipField = "";
        }
      }
    }
  }

  var string = buffer.toString();
  return newValue.copyWith(
      text: string,
      selection: TextSelection.collapsed(offset: string.length));
  }
}

Upvotes: 7

Related Questions