Home > database >  How to update a field in Firebase when using a datatable?
How to update a field in Firebase when using a datatable?

Time:06-14

How can I update a specific field in my Datatable. I am using this package: https://pub.dev/packages/responsive_table

When I tap on one item in my Datatable it opens a Dialog where I have my TextController and a ElevatedButton for updating my values. All that seems to work, I click on one item, the right name of that item is stored in my TextController. But when I press my button, it's updating some random item in my Firebase and not the value that i clicked in the first place.

Here is my code:

class _UsersPageState extends State<UsersPage> {

 
  var nameController = TextEditingController();


  @override
  Widget build(BuildContext context) {
    final UserTableProvider usertablesProvider = Provider.of<UserTableProvider>(context);
    return SingleChildScrollView(
        child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            mainAxisSize: MainAxisSize.max,
            children: [
              Container(
                margin: EdgeInsets.all(10),
                padding: EdgeInsets.all(0),
                constraints: BoxConstraints(
                  maxHeight: 700,
                ),
                child: Card(
                  elevation: 1,
                  shadowColor: Colors.black,
                  clipBehavior: Clip.none,
                  child: ResponsiveDatatable(
                    title: TextButton.icon(
                      onPressed: () => {
                        addUserDialog(context),
                      },
                      icon: Icon(Icons.add),
                      label: Text("Legg til bruker"),
                    ),
                    reponseScreenSizes: [ScreenSize.xs],
                    actions: [
                      if (usertablesProvider.isSearch)
                        Expanded(
                            child: TextField(
                              decoration: InputDecoration(
                                hintText: 'Søk på ansattnr..',
                                  prefixIcon: IconButton(
                                      icon: Icon(Icons.cancel),
                                      onPressed: () {
                                        setState(() {
                                          usertablesProvider.isSearch = false;
                                        });
                                      }),
                                  suffixIcon: IconButton(
                                      icon: Icon(Icons.search), onPressed: () {})),
                              onSubmitted: (value) {
                                usertablesProvider.filterData(value);
                              },
                            )),
                      if (!usertablesProvider.isSearch)
                        IconButton(
                            icon: Icon(Icons.search),
                            onPressed: () {
                              setState(() {
                                usertablesProvider.isSearch = true;
                              });
                            }),

                    ],
                    headers: usertablesProvider.userTableHeader,
                    source: usertablesProvider.source,
                    selecteds: usertablesProvider.selecteds,
                    showSelect: usertablesProvider.showSelect,
                    autoHeight: false,
                    onSort: (value) {
                      setState(() => usertablesProvider.isLoading = true);

                      setState(() {
                        usertablesProvider.sortColumn = value;
                        usertablesProvider.sortAscending = !usertablesProvider.sortAscending;
                        if (usertablesProvider.sortAscending) {
                          usertablesProvider.sourceFiltered.sort((a, b) =>
                              b["${usertablesProvider.sortColumn}"].compareTo(a["${usertablesProvider.sortColumn}"]));
                        } else {
                          usertablesProvider.sourceFiltered.sort((a, b) =>
                              a["${usertablesProvider.sortColumn}"].compareTo(b["${usertablesProvider.sortColumn}"]));
                        }
                        var _rangeTop = usertablesProvider.currentPerPage! < usertablesProvider.sourceFiltered.length
                            ? usertablesProvider.currentPerPage!
                            : usertablesProvider.sourceFiltered.length;
                        usertablesProvider.source = usertablesProvider.sourceFiltered.getRange(0, _rangeTop).toList();
                        usertablesProvider.searchKey = value;

                        usertablesProvider.isLoading = false;
                      });
                    },
                    expanded: usertablesProvider.expanded,
                    sortAscending: usertablesProvider.sortAscending,
                    sortColumn: usertablesProvider.sortColumn,
                    isLoading: usertablesProvider.isLoading,
                    onTabRow: (data){
                      
                      updateUserDialog(context);
                      print(data);

                      nameController.text = data['name'];
                      
                    },
                    onSelect: (value, item) {
                      print("$value  $item ");
                      if (value!) {
                        setState(() => usertablesProvider.selecteds.add(item));
                      } else {
                        setState(
                                () => usertablesProvider.selecteds.removeAt(usertablesProvider.selecteds.indexOf(item)));
                      }
                    },
                    onSelectAll: (value) {
                      if (value!) {
                        setState(() => usertablesProvider.selecteds =
                            usertablesProvider.source.map((entry) => entry).toList().cast());
                      } else {
                        setState(() => usertablesProvider.selecteds.clear());
                      }
                    },
                    footers: [
                      Container(
                        padding: EdgeInsets.symmetric(horizontal: 15),
                        child: Text("Rader per side:"),
                      ),
                      if (usertablesProvider.perPages.isNotEmpty)
                        Container(
                          padding: EdgeInsets.symmetric(horizontal: 15),
                          child: DropdownButton<int>(
                            value: usertablesProvider.currentPerPage,
                            items: usertablesProvider.perPages
                                .map((e) => DropdownMenuItem<int>(
                              child: Text("$e"),
                              value: e,
                            ))
                                .toList(),
                            onChanged: (dynamic value) {
                              setState(() {
                                usertablesProvider.currentPerPage = value;
                                usertablesProvider.currentPage = 1;
                                usertablesProvider.resetData();
                              });
                            },
                            isExpanded: false,
                          ),
                        ),
                      Container(
                        padding: EdgeInsets.symmetric(horizontal: 15),
                        child:
                        Text("${usertablesProvider.currentPage} - ${usertablesProvider.currentPerPage} of ${usertablesProvider.total}"),
                      ),
                      IconButton(
                        icon: Icon(
                          Icons.arrow_back_ios,
                          size: 16,
                        ),
                        onPressed: usertablesProvider.currentPage == 1
                            ? null
                            : () {
                          var _nextSet = usertablesProvider.currentPage - usertablesProvider.currentPerPage!;
                          setState(() {
                            usertablesProvider.currentPage = _nextSet > 1 ? _nextSet : 1;
                            usertablesProvider.resetData(start: usertablesProvider.currentPage - 1);
                          });
                        },
                        padding: EdgeInsets.symmetric(horizontal: 15),
                      ),
                      IconButton(
                        icon: Icon(Icons.arrow_forward_ios, size: 16),
                        onPressed: usertablesProvider.currentPage   usertablesProvider.currentPerPage! - 1 > usertablesProvider.total
                            ? null
                            : () {
                          var _nextSet = usertablesProvider.currentPage   usertablesProvider.currentPerPage!;

                          setState(() {
                            usertablesProvider.currentPage = _nextSet < usertablesProvider.total
                                ? _nextSet
                                : usertablesProvider.total - usertablesProvider.currentPerPage!;
                            usertablesProvider.resetData(start: _nextSet - 1);
                          });
                        },
                        padding: EdgeInsets.symmetric(horizontal: 15),
                      )
                    ],
                  ),
                ),
              ),
            ])
    );

  }

  updateUserDialog(BuildContext context){
    return showDialog(context: context, builder: (context) {
      return Dialog(
        child: Container(
          child: SizedBox(
            width: 600,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text('Endre bruker', style: TextStyle(
                    fontWeight: FontWeight.bold
                ),),
                SizedBox(
                  height: 10,
                ),
                TextField(
                  controller: nameController,
                  decoration: const InputDecoration(
                      labelText: 'Navn',
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.grey,
                        ),
                      ),
                      border: OutlineInputBorder(
                          borderSide: BorderSide(color: Colors.grey)
                      )
                  ),
             
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.grey,
                        ),
                      ),
                      border: OutlineInputBorder(
                          borderSide: BorderSide(color: Colors.grey)
                      )
                  ),
                ),
               
                ElevatedButton(
                    onPressed: () async {
                      var name = nameController.text.trim();
              

                      FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;

                      FirebaseAuth auth = FirebaseAuth.instance;

                      User? user = auth.currentUser;



                      await firebaseFirestore.collection('users').doc(user!.uid).update({
                        'navn': name,
               

                      });


                      nameController.text = '';


                    },
                    child: const Text('Save')),
                const SizedBox(
                  height: 10,
                ),
              ],
            ),
          ),
        ),
      );
    });
  }    


    class UserTableProvider with ChangeNotifier {

  List<DatatableHeader> userTableHeader = [
    DatatableHeader(
        text: "Ansattnr",
        value: "empnumber",
        show: true,
        flex: 1,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "Navn",
        value: "name",
        show: true,
        flex: 6,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "Epost",
        value: "email",
        show: true,
        flex: 4,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "",
        value: "uid",
        show: false,
        sortable: true,
        textAlign: TextAlign.center),
    DatatableHeader(
        text: "Tlf",
        value: "tlfnumber",
        show: true,
        flex: 2,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "Eget verktøy",
        value: "owntool",
        show: false,
        sortable: true,
        textAlign: TextAlign.left),

  ];

  final List<int> perPages = [10, 20, 50, 100];
  int total = 100;
  int? currentPerPage = 10;
  int currentPage = 1;
  List<bool>? expanded;
  String? searchKey = "empnumber";

  bool isSearch = false;
  List<Map<String, dynamic>> sourceOriginal = [];
  List<Map<String, dynamic>> sourceFiltered = [];
  List<Map<String, dynamic>> source = [];
  List<Map<String, dynamic>> selecteds = [];
  // ignore: unused_field
  final String selectableKey = "id";

  String? sortColumn;
  bool sortAscending = true;
  bool isLoading = true;
  final bool showSelect = true;

  final UserServices _userServices = UserServices();
  List<UserModel> _users = <UserModel>[];
  List<UserModel> get users => _users;

  Future _loadFromFirebase() async {
    _users = await _userServices.getAllUsers();

  }

  List<Map<String, dynamic>> _getUsersData() {
    isLoading = true;
    List<Map<String, dynamic>> temps = [];
    var i = users.length;
    if (kDebugMode) {
      print(i);
    }
    // ignore: unused_local_variable
    for (UserModel userData in users) {
      if (kDebugMode) {
        print(userData.name);
      }
      if (kDebugMode) {
        print(userData.email);
      }
      temps.add({
        "empnumber": userData.empnumber,
        "email": userData.email,
        "name": userData.name,
        "uid": userData.uid,
        "owntool": userData.owntool,
        "tlfnumber": userData.tlfnumber,
      });
      i  ;
    }


    return temps;
  }

  _initData() async {
    await _loadFromFirebase();
    mockPullData();
    notifyListeners();

  }

  mockPullData() async {
    expanded = List.generate(currentPerPage!, (index) => false);

    isLoading = true;
    Future.delayed(const Duration(seconds: 3)).then((value) {
      sourceOriginal.clear();
      sourceOriginal.addAll(_getUsersData());
      sourceFiltered = sourceOriginal;
      total = sourceFiltered.length;
      source = sourceFiltered.getRange(0, _users.length).toList();
      isLoading = false;
      notifyListeners();
    });
  }

  resetData({start: 0}) async {
    isLoading = true;
    var expandedLen =
    total - start < currentPerPage! ? total - start : currentPerPage;
    Future.delayed(const Duration(seconds: 0)).then((value) {
      expanded = List.generate(expandedLen as int, (index) => false);
      source.clear();
      source = sourceFiltered.getRange(start, start   expandedLen).toList();
      isLoading = false;
      notifyListeners();
    });
  }

  filterData(value) {
    isLoading = true;

    try {
      if (value == "" || value == null) {
        source = sourceOriginal;
      } else {
        sourceFiltered = sourceOriginal
            .where((data) => data[searchKey!]
            .toString()
            .toLowerCase()
            .contains(value.toString().toLowerCase()))
            .toList();
      }

      total = sourceFiltered.length;
      var _rangeTop = total < currentPerPage! ? total : currentPerPage!;
      expanded = List.generate(_rangeTop, (index) => false);
      source = sourceFiltered.getRange(0, _rangeTop).toList();
    } catch (e) {
      print(e);
    }
    isLoading = false;
    notifyListeners();
  }


  UserTableProvider.init() {
    _initData();
  }
}

CodePudding user response:

The problem is the user id you are using to update the firestore document, the current user's id not the user id from the data.

Please edit your updateUserDialog method, add the data as a parameter for the function. Something like updateUserDialog(BuildContext context, Map<String, dynamic> data). This will avail the whole data Map within the method. This will expose the uid for you to use to update the right document. You can then pass uid from the data Map as the doc as shown below.

await firebaseFirestore.collection('users').doc(userId).update({
  'navn': name,
});

For the snippet above, the uid is stored in a variable userId.

Below is the complete updated method you can work with.

updateUserDialog(BuildContext context, Map<String, dynamic> data) {
    nameController.text = data['name'];
    String userId = data['uid'].toString();

    return showDialog(
      context: context,
      builder: (context) {
        return Dialog(
          child: Container(
            child: SizedBox(
              width: 600,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Text(
                    'Endre bruker',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  TextField(
                    controller: nameController,
                    decoration: const InputDecoration(
                        labelText: 'Navn',
                        enabledBorder: OutlineInputBorder(
                          borderSide: BorderSide(
                            color: Colors.grey,
                          ),
                        ),
                        border: OutlineInputBorder(
                            borderSide: BorderSide(color: Colors.grey))),
                  ),
                  ElevatedButton(
                      onPressed: () async {
                        var name = nameController.text.trim();

                        FirebaseFirestore firebaseFirestore =
                            FirebaseFirestore.instance;

                      
                        await firebaseFirestore
                            .collection('users')
                            .doc(userId)
                            .update({
                          'navn': name,
                        });

                        nameController.text = '';
                      },
                      child: const Text('Save')),
                  const SizedBox(
                    height: 10,
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }

You might as well update your onTabRow function to

onTabRow: (data) {
   updateUserDialog(context, data);
},

That should solve your issue.

  • Related