0

I'm trying to adapt some code to sort on a multidimensional array. But I can't recreate the filtered array to retrieve the sets of elements.

Here is the original code:

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  TextEditingController _textController = TextEditingController();
  List<String> initialList = ["Chat", "Chien", "Rat", "Cheval", "Ours"];
  List<String> filteredList = List();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Test search')),
        body: Column(
          children: <Widget>[
            TextField(
              controller: _textController,
              onChanged: (text) {
                text = text.toLowerCase();
                setState(() {
                  filteredList = initialList
                      .where((element) => element.toLowerCase().contains(text))
                      .toList();
                });
              },
            ),
            if (filteredList.length == 0 && _textController.text.isEmpty)
              Expanded(
                  child: ListView.builder(
                      itemCount: initialList.length,
                      itemBuilder: (BuildContext context, index) {
                        return Container(
                          height: 50,
                          child: Text(initialList[index]),
                        );
                      }))
            else if (filteredList.length==0 && _textController.text.isNotEmpty)
              Expanded(
                child: Container(
                  child: Text('Aucune donnée'),
                ),
              )
            else
              Expanded(
                child: ListView.builder(
                    itemCount: filteredList.length,
                    itemBuilder: (BuildContext context, index) {
                      return Container(
                        height: 50,
                        child: Text(filteredList[index]),
                      );
                    }),
              ),
          ],
        ));
  }
}

And my modified code:

import 'package:flutter/material.dart';

  class Houblons extends StatefulWidget {
     @override
     _HoublonsState createState() => _HoublonsState();
  }

  class _HoublonsState extends State<Houblons> {
   TextEditingController _textController = TextEditingController();
   //List<String> initialList = ["Chat", "Chien", "Rat", "Cheval", "Ours"];


  List<ListeElements> initialList = [
     new ListeElements (nom : "testa", lienp: 1),
     new ListeElements (nom : "testaa", lienp: 2),
     new ListeElements (nom : "testaa b", lienp: 2),
     new ListeElements (nom : "testaa bb", lienp: 2),
     new ListeElements (nom : "testaa bb c", lienp: 2),
  ];


  List<ListeElements2> filteredList = List();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Houblons')),
      body: Column(
        children: <Widget>[
          TextField(
             controller: _textController,
             onChanged: (text) {
               text = text.toLowerCase();
               setState(() {

               filteredList = initialList
               .where((element) => element.nom.contains(text)).cast<String>()
               .toList();
              });
            },
           decoration: new InputDecoration(
           labelText: "Champ de recherche",
         ),
        ),
        if (filteredList.length == 0 && _textController.text.isEmpty)
         Expanded(
          child: ListView.builder(
          itemCount: initialList.length,
          itemBuilder: (BuildContext context, index) {
            return Container(
              height: 50,
              child: Text(initialList[index].nom),
            );
           }))else if (filteredList.length==0 && _textController.text.isNotEmpty)
             Expanded(
               child: Container(
                 child: Text('Aucune donnée'),
                ),
             )else
               Expanded(
                 child: ListView.builder(
                 itemCount: filteredList.length,
                 itemBuilder: (BuildContext context, index) {
                   return Container(
                      height: 50,
                      child: Text(filteredList[index].nom),
                  );
                }),
              ),
            ],
       ));
  }

  }

class ListeElements {
  String nom;
  int lienp;

  ListeElements({String nom, int lienp}){
    this.nom = nom;
    this.lienp = lienp;
  }
 }

class ListeElements2 {
  String nom;
  int lienp;

  ListeElements2({String nom, int lienp}){
    this.nom = nom;
    this.lienp = lienp;
  }
}

I planned after to make a listview with a link on each element which will display an alert with elements coming from the multidimensional table.

Thank you for your help.

Thanks, but I can't. I found some code that works with a json list from an online list, but when that created the list its not working. I can't find the mistake I'm making, Yet I think it's simple but I'm blocking. I can't find an example code online

The original code:

a link!

here is my code:

import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;

class TestFilter extends StatefulWidget {
  TestFilter() : super();

  final String title = "Filter List Demo";

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

class Debouncer {
  final int milliseconds;
  VoidCallback action;
  Timer _timer;

  Debouncer({this.milliseconds});

  run(VoidCallback action) {
    if (null != _timer) {
      _timer.cancel();
    }
    _timer = Timer(Duration(milliseconds: milliseconds), action);
  }
}

class TestFilterState extends State<TestFilter> {


  final _debouncer = Debouncer(milliseconds: 500);

  List<User> filteredUsers = List();
  List<User> users = [
    {'id': 40, 'name': "moia", 'email': "test@1.com"},
    {'id': 40, 'name': "moiaa", 'email': "test@2.com"},
    {'id': 40, 'name': "moiab", 'email': "test@3.com"},
   ];
  @override
  void initState() {
    super.initState();
       setState(() {
        users = filteredUsers;
      });

  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: <Widget>[
          TextField(
            decoration: InputDecoration(
              contentPadding: EdgeInsets.all(15.0),
              hintText: 'Filter by name or email',
            ),
            onChanged: (string) {
              _debouncer.run(() {
                setState(() {
                  filteredUsers = users
                      .where((u) => (u.name
                      .toLowerCase()
                      .contains(string.toLowerCase()) ||
                      u.email.toLowerCase().contains(string.toLowerCase())))
                      .toList();
                });
              });
            },
          ),
          Expanded(
            child: ListView.builder(
              padding: EdgeInsets.all(10.0),
              itemCount: filteredUsers.length,
              itemBuilder: (BuildContext context, int index) {
                return Card(
                  child: Padding(
                    padding: EdgeInsets.all(10.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          filteredUsers[index].name,
                          style: TextStyle(
                            fontSize: 16.0,
                            color: Colors.black,
                          ),
                        ),
                        SizedBox(
                          height: 5.0,
                        ),
                        Text(
                          filteredUsers[index].email.toLowerCase(),
                          style: TextStyle(
                            fontSize: 14.0,
                            color: Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

class User {
  int id;
  String name;
  String email;

  User({this.id, this.name, this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json["id"] as int,
      name: json["name"] as String,
      email: json["email"] as String,
    );
  }
}

Davweb
  • 27
  • 1
  • 6
  • I don't think the original code is sorting the entered values, instead it is just checking if entered text is present in `initialList` and appends it to `filteredList` – Joy Terence Nov 11 '20 at 17:09
  • ha, i didn't use the right method. it can't be adapted? do you know a sorting method with a multidimensional array? – Davweb Nov 12 '20 at 01:26
  • a multidimensional array is an array of arrays, something like this `initialList[][]`, but in your case this is still an array but an array of single objects i.e. `initialList[]` – Joy Terence Nov 12 '20 at 05:36
  • I feel that what you really need is to sort `initialList[]` array consisting of `ListeElements` based on the text that is present in `nom` field of `ListeElements`. In that case, you can pass a custom comparison logic to the `sort` method. This [how-can-i-sort-a-list-of-strings-in-dart](https://stackoverflow.com/questions/12888206/how-can-i-sort-a-list-of-strings-in-dart) and this [dart-comparison-operators](https://stackoverflow.com/questions/55297580/dart-comparison-operators/55308336#55308336) provide more info on how to achieve this. – Joy Terence Nov 12 '20 at 05:39

1 Answers1

0

Are you sorting the List ascending/descending? List.sort() can be applied to multidimensional array/List.

This sorts the name in ascending order

filteredUsers = users.sort((a, b) => 
    a.name.toLowerCase().compareTo(b.name.toLowerCase()));                      

For descending, you just need to swap a and b

filteredUsers = users.sort((b, a) => 
    a.name.toLowerCase().compareTo(b.name.toLowerCase()));                      

I've also tested out the filter that you've applied on the List. The filter works without issues. The issue here is that you're adding incompatible type to List<User>. Changing it to List works without issues.

List users = [
  {'id': 40, 'name': "moia", 'email': "test@1.com"},
  {'id': 40, 'name': "moiaa", 'email': "test@2.com"},
  {'id': 40, 'name': "moiab", 'email': "test@3.com"},
  ];
  
String keyword = 'moiaa';
filtered = users.where((a) => a['name'].contains(keyword.toLowerCase()) ||
                      a['email'].toLowerCase().contains(keyword.toLowerCase())).toList();

print(filtered);

The output should print [{id: 40, name: moiaa, email: test@2.com}]

If you'd like to use the User object in the List as List<User>. The List items should be added using the constructor.

List<User> users = [
  User(id: 40, name: "moia", email: "test@1.com"),
  User(id: 40, name: "moiaa", email: "test@2.com"),
  User(id: 40, name: "moiab", email: "test@3.com"),
];
  
String keyword = 'moiaa';
filtered = users.where((a) => a.name.contains(keyword.toLowerCase()) ||
                      a.email.toLowerCase().contains(keyword.toLowerCase())).toList();

for(User user in filtered){
  print('id: ${user.id} name: ${user.name} email: ${user.email}');
}

The output should print: id: 40 name: moiaa email: test@2.com

Omatt
  • 8,564
  • 2
  • 42
  • 144