Search code examples
regexflutterdarttextformfieldtexteditingcontroller

How to remove hashtags with the word attached to them in Flutter TextFields?


I am trying to capture any words attached to a hashtag symbol to add it to a list and then remove it from the TextFormField. I have searched a lot for a solution but I didn't find a good one also I tried myself. But after a long time of trying to found out a solution with chat-gpt, I didn't get the expected result. The problem is that it works for the first time but then it become capturing only the first letter after the hashtag

here's the expected result:

but this is the result after trying:

here's my code:

  TextEditingController _controller = TextEditingController();
  List<String> _removedWords = [];

  @override
  void initState() {
    super.initState();
    _controller.addListener(_removeHashtagWord);
  }

  void _removeHashtagWord() {
    String text = _controller.text;

    if (text.contains('#') && text.endsWith(' ')) {
      RegExp hashtagPattern = RegExp(r'#\S+\b');
      Iterable<RegExpMatch> matches = hashtagPattern.allMatches(text);

      if (matches.isNotEmpty) { 
        RegExpMatch match = matches.first;
        String removedWord = match.group(0)!;
        print(removedWord);

        setState(() {
          _removedWords.add(removedWord);
          _controller.text = text.replaceFirst(removedWord, '');
          text = _controller.text;
          _controller.selection = TextSelection.collapsed(
            offset: match.start,
          );
        });
      }
    }
  }

the build function:

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          TextField(
            controller: _controller,
            decoration: const InputDecoration(hintText: 'Type here...'),
          ),
          const SizedBox(height: 16),
          const Text('Removed words:'),
          const SizedBox(height: 8),
          Expanded(
            child: ListView.builder(
              itemCount: _removedWords.length,
              itemBuilder: (context, index) {
                return Text(_removedWords[index]);
              },
            ),
          ),
        ],
      ),
    );
  }

Solution

  • Your problem is that you leave space in your input field while removing first hashtag.

    After removing your field is something like this: asd ss| , where | is position of cursor.

    Remove hashtag including trailing space with, for example with expression #\S+\s.

    If you need, you can later remove trailing space it in your code:

    removedWord.trim()