Abdullah Khudher
Abdullah Khudher

Reputation: 309

checking if a long sentence contains a short sentence from TextField, Dart

I want to search for a short sentence inside a long sentence ...

it is working fine with this demo:

        String a = 'from first day i was very good';
        String b = 'from first day';
        print(a.contains(b));

result : true

but when I use TextField to enter a short sentence and check it if is exciting in a long sentence ... TextField when I enter space between words doesn't show any result

Note: this app in the Arabic language and doesn't work on an android and IOS ... in English worked well in the IOS simulator but doesn't work on an android phone.

my all code:

import 'dart:convert';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:egyptian_ads_app/constant/constant.dart';
import 'package:egyptian_ads_app/pages/business_man_pages/business_man_page.dart';
import 'package:egyptian_ads_app/pages/starting_page/landing_service_page.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:share/share.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';

class ItemModel {
  ItemModel(
      {this.id,
      this.title,
      this.imagePath,
      this.about,
      this.phoneNumber,
      this.traderId,
      this.type,
      this.city});

  int id;
  String title;
  String imagePath;
  String about;
  String phoneNumber;
  int traderId;
  String type;
  String city;

  factory ItemModel.fromJson(Map<String, dynamic> json) {
    return new ItemModel(
      id: json['id'],
      title: json['name'],
      imagePath: json["logo"]['url'],
      about: json['about'],
      phoneNumber: json['phone_number'],
      traderId: json['trader_id'],
      type: json['category']['type'],
      // city: json['city'],
    );
  }
}


class InstantSearchPage extends StatefulWidget {
  @override
  _InstantSearchPageState createState() => _InstantSearchPageState();
}

class _InstantSearchPageState extends State<InstantSearchPage> {
  TextEditingController _searchController = TextEditingController();

  Future resultsLoaded;
  List<ItemModel> _allResults = [];
  List<ItemModel> _resultsList = [];

  @override
  void initState() {
    super.initState();
    _searchController.addListener(_onSearchChanged);
  }

  @override
  void dispose() {
    _searchController.removeListener(_onSearchChanged);
    _searchController.dispose();
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    resultsLoaded = getUserDetails();
  }

  getUserDetails() async {
    final String url = 'https://yallservice.com/api/v1/departments';
    final response = await http.get(url);
    final responseJson = json.decode(response.body);
    var data = responseJson['data'];
    setState(() {
      for (Map user in data) {
        _allResults.add(ItemModel.fromJson(user));
      }
    });

    searchResultsList();
    return "complete";
  }

  _onSearchChanged() {
    searchResultsList();
  }

  searchResultsList() {
    List<ItemModel> showResults = [];

    if (_searchController.text != "") {
      for (var tripSnapshot in _allResults) {
        String title = tripSnapshot.about;
        print(title + title);
        if (title.contains(_searchController.text)) {
          showResults.add(tripSnapshot);
        }
      }
    } else {
      showResults = List.from(_allResults);
    }
    setState(() {
      _resultsList = showResults;
    });
  }

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: BackButton(),
        title: Container(
          color: Colors.white,
          child: TextField(
            controller: _searchController,
            decoration: InputDecoration(prefixIcon: Icon(Icons.search)),
          ),
        ),
      ),
      body: Container(
        color: Colors.grey.shade300,
        child: Column(
          children: <Widget>[
            Expanded(
                child: ListView.builder(
              itemCount: _resultsList.length,
              itemBuilder: (BuildContext context, int index) {
                return Container(
                    color: Colors.white,
                    child: ListTile(
                      subtitle: Text(_resultsList[index].about),
                    ));
                // return Card(
                //   index: index,
                //   data: _resultsList,
                // );
              },
            )),
          ],
        ),
      ),
    );
  }
}

Upvotes: 0

Views: 198

Answers (2)

Abdullah Khudher
Abdullah Khudher

Reputation: 309

I fixed the problem just by putting textDirection: TextDirection.rtl, to my TextField

Upvotes: 0

Thierry
Thierry

Reputation: 8393

This is due to the encoding of white spaces in RTL strings.

Try to trim the TextField text before you search for it.

Special trim method

String trim(String string) {
  assert(string != null);
  final stringList = string.characters.toList();
  final whitespaces = ['8206', '8207', '32'];
  while (whitespaces.contains(stringList.last.runes.join()))
    stringList.removeLast();
  while (whitespaces.contains(stringList.first.runes.join()))
    stringList.remove(stringList.first);
  return stringList.join();
}

Updated searchResultsList

searchResultsList() {
  List<ItemModel> showResults = [];
  if (_searchController.text != "") {
    for (var tripSnapshot in _allResults) {
      String title = tripSnapshot.about;
      if (title.contains(trim(_searchController.text))) {
        showResults.add(tripSnapshot);
      }
    }
  } else {
    showResults = List.from(_allResults);
  }
  setState(() {
    _resultsList = showResults;
  });
}

Ref: Text fields' values do not get trimmed correctly when textDirection: TextDirection.rtl #68093


Improvement

Your search is currently case-sensitive. Maybe you should make it case-insensitive?

searchResultsList() {
  setState(() {
    _resultsList = _searchController.text.isNotEmpty
        ? _allResults
            .where((tripSnapshot) => tripSnapshot.about
                .toLowerCase()
                .contains(trim(_searchController.text).toLowerCase()))
            .toList()
        : List.from(_allResults);
  });
}

Upvotes: 1

Related Questions