Function to create buttons according to the database

Asked

Viewed 32 times

0

I have in my database several information and that for each information there should be a button that directs the user to the screen where a guide will be displayed according to the chosen option. However, the number of data in the database must change according to the user, that is, I need a function that reads the database, identify how many buttons should be created and then create the buttons...

import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'Embarque.dart';
import 'Settings.dart';
import 'package:cargas_app/database/sqlite/connection.dart';

class menu extends StatefulWidget {
  const menu({Key? key}) : super(key: key);

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

class _menuState extends State<menu> {
  String num_embarque = "";
  var total_embarques = 0;
  var j = 0;
  String? nm_emb = "";



//Função que faz a leitura no banco, retorna o numero dos embarques e a quantidade

  ler_embarque() async {
    final Database db = await Connection.get;
    List<Map<String, dynamic>> url =
        await db.rawQuery('SELECT nr_embarque FROM embarque');
    var embarques = url.forEach((row) => print(row));

    List<Map<String, dynamic>> conta_embarques =
        await db.rawQuery('SELECT COUNT(nr_embarque) FROM embarque');
    String cont_embarques = conta_embarques.toString();
    var cont = RegExp(r'(?<= )(.*)(?=})');
    var match0 = cont.firstMatch(cont_embarques);
    var total_embarques_string = match0?.group(0);
    total_embarques = int.parse('$total_embarques_string');
    print("Embarques: $total_embarques"); //mostra o total de embarques

    while (j < total_embarques) {
      List nr_embarque = url;
      num_embarque = nr_embarque[j].toString();

      var re = RegExp(r'(?<= )(.*)(?=})');
      var match1 = re.firstMatch(num_embarque);
      nm_emb = match1?.group(0);

      print(j);
      print(nm_emb);

      j++;
      return add_buttom();
    }
  }


//Função que adiciona o botão, ao meu entendimento se fez necessário chamar a função do banco dentro da função do botão, por conta de não poder ser uma função async

  add_buttom() {
    if (j == 0) {
      ler_embarque();
    } else {
      setState(() {
        ElevatedButton(
          child: Text(
            "Embarque: $nm_emb",
            textAlign: TextAlign.center,
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
          ),
          style: ElevatedButton.styleFrom(
            primary: Color(0xffbDCDCDC),
            onPrimary: Colors.black,
          ),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => Embarque(),
              ),
            );
          },
        );
      });

      if (j > total_embarques) {
        return add_buttom();
      } else {
        return ler_embarque();
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    new Container();
    return Scaffold(
      appBar: AppBar(
        brightness: Brightness.dark,
        automaticallyImplyLeading: false,
        title: Text("Embarques"),
        backgroundColor: Color(0xffb0000CD),
      ),
      body: Container(
        padding: EdgeInsets.all(32),
        decoration: BoxDecoration(color: Colors.grey[400]),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ConstrainedBox(
              constraints: BoxConstraints.tightFor(width: 1000, height: 50),
              child: add_buttom(),
            ),
            SizedBox(
              height: 32,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => Settings(),
            ),
          );
        },
        child: const Icon(Icons.settings),
        backgroundColor: Color(0xffb0000CD),
      ),
    );
  }
}

...when arriving at Child, inside the Constrainedbox, I have the function "add_button()", which has the reading executed in the database (ler_shipment()), returns the necessary values and calls an Elevatedbutton. Until the reading part in the bank it works right and displays the requested information on the console, but when creating the Elevatedbutton I get:

════════ Exception caught by widgets library ═══════════════════════════════════
The following _TypeError was thrown building menu(dirty, state: _menuState#7a0ff):
type 'Future<dynamic>' is not a subtype of type 'Widget'

The relevant error-causing widget was
menu
lib\pages\Login.dart:39
When the exception was thrown, this was the stack

  • still unanswered...

1 answer

1

Hello

Your add_button function is not returning any element (Widget), however it is being used as if a widget would result

add_buttom() {
if (j == 0) {
  ler_embarque();
} else {
  setState(() {
    ElevatedButton(  ///<---------- aqui deveria ser um return ElevatedButton(
      child: Text(
        "Embarque: $nm_emb",

In this case, according to your body: the same is waiting for a widget coming from the function add_buttom

 body: Container(
    padding: EdgeInsets.all(32),
    decoration: BoxDecoration(color: Colors.grey[400]),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        ConstrainedBox(
          constraints: BoxConstraints.tightFor(width: 1000, height: 50),
          child: add_buttom(),
        ),
        SizedBox(
          height: 32,
        ),
      ],
    ),
  ),

In addition your code can improve in terms of separation of functions, as it is not clear the objective and whether the functions will result in what you are expecting.

A good way is to separate the functions that return Widgets from those that serve only to ensure data logic. For example, the ler_shipment function should not be inserted in the add_buttom() function, because first I think you should assemble your list and then call the function that will draw the list on the screen.

How you are using the Statefullwidget try placing the function calls that will mount the tables in the initState of your form.

In your build is also not necessary this Container at the beginning:

  @override
  Widget build(BuildContext context) {
    new Container();   /// <--- sem finalidade
    return Scaffold(

Anyway, when you’re learning, that’s what happens. But, my final tip is: - Make a list with the buttons, improve the le_embarkation routine to add elements in the list and then implement within the build the routine that draws the buttons on the screen.

If you do, post it on github, because it might make it easier for people to help you. Success there.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.