i trying to do a dynamic table when the user touches add botton a row will be displayed,in the final column i have a group of bottons, when the user touches the add botton will be add a form widget, but if add so much, the scrolling dont work, i show you my code and some pictures.
import 'package:flutter/material.dart';
import 'package:simao/themes/themes.dart';
import 'package:simao/widgets/widgets.dart';
class FormLicitacion extends StatefulWidget {
FormLicitacion ({super.key});
@override
State<FormLicitacion> createState() => _FormLicitacionState();
}
class _FormLicitacionState extends State<FormLicitacion> {
final _formKey = GlobalKey<FormState>();
// List<Map <String, List<String>>> fechasOfEquipos = [{"0":['2023-02-15',]}];
List<Map<String, String>> formEquipo = [];
List<List<String>> datesOfEquipos = [];
Map<String, String> formContrato = {};
Map<String, String> formFilterValues = {};
Map<String, String> formValues = {};
List<Widget> rowsEquipos = [];
List<int> equiposCount = [];
List<double> columnsWidth = [100, 200, 200, 200, 200, 200, 250, 200, 200, 200];
List<String> columnsName = ['No','Clave','Identificador','Nombre','Descripcion','Cantidad','Categoria','Fechas', 'Actividades', 'Acciones'];
void resetFormFilters(){
setState(() {
formFilterValues = {
'clave_filtro': '',
'identificador_filtro': '',
'nombre_filtro': '',
'descripcion_filtro': '',
'categorias_filtro': '',
'subcategorias_filtro':'',
};
});
}
void resetFormContrato(){
setState(() {
formContrato = {
'id': '',
'empresas_id': '',
'clientes_id': '',
'periodicidad_id': '',
'sucursal_id': '',
'fecha_inicio': '',
'fecha_final': '',
'clave': '',
'nombre': '',
'monto': '',
'descripcion': '',
};
});
}
void initEquipos({int index = 0}){
setState(() {
rowsEquipos = [
CustomInputField(formProperty: "No", formValues: formEquipo[index], heightOfSizedBox: 0, readOnly: true, labelText: "No", hintText: "No"),
CustomInputField(formProperty: "clave", formValues: formEquipo[index], heightOfSizedBox: 0, labelText: "Clave", hintText: "Clave"),
CustomInputField(formProperty: "identificador", formValues: formEquipo[index], heightOfSizedBox: 0, labelText: "Identificador", hintText: "Identificador"),
CustomInputField(formProperty: "nombre", formValues: formEquipo[index], heightOfSizedBox: 0, maxLines: 5, labelText: "Nombre", hintText: "Nombre"),
CustomInputField(formProperty: "descripcion", formValues: formEquipo[index], heightOfSizedBox: 0, maxLines: 5, labelText: "Descripcion", hintText: "Descripcion"),
CustomInputField(formProperty: "cantidad", formValues: formEquipo[index], heightOfSizedBox: 0, onlyNumber: true, keyboardType: TextInputType.number, labelText: "Cantidad", hintText: "Cantidad"),
Column(
children: [
const SizedBox(height: 10),
CustomDropDownCustom1(message: "Selecciona Categoria", formValues: formEquipo[index], formProperty: "categorias_id", heightOfSizedBox: 0, ),
Text("Sub Categoria", style: TextStyle(fontWeight: FontWeight.bold)),
CustomDropDownCustom1(message: "Selecciona Sub Categoria", formValues: formEquipo[index], formProperty: "subcategorias_id", heightOfSizedBox: 0,),
Text("Precio Unitario", style: TextStyle(fontWeight: FontWeight.bold)),
CustomInputField(formProperty: "precio_unitario", formValues: formEquipo[index], heightOfSizedBox: 0, onlyNumber: true, keyboardType: TextInputType.number, labelText: "Precio Unitario", hintText: "Precio Unitario"),
],
),
CustomInputField(formProperty: "tareas_id", formValues: formEquipo[index], heightOfSizedBox: 0,),
// THIS IS THE PROBLEM
// THE SINGLE CHILD SCROLL VIEW IS NOT SCROLLING
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
for(var wid in initWidgetDates(index: index)) wid,
],
),
),
Column(
children: [
TextButton(child: Icon(Icons.add, color: Color.fromARGB(255, 255, 255, 255)), onPressed: (){addDate(index: index);}, style: TextButton.styleFrom(backgroundColor: AppTheme.successColor),),
TextButton(child: Icon(Icons.remove, color: Color.fromARGB(255, 255, 255, 255)), onPressed: (){deleteDate(index: index);}, style: TextButton.styleFrom(backgroundColor: AppTheme.successColor)),
TextButton(child: Icon(Icons.delete, color: Color.fromARGB(255, 255, 255, 255)), onPressed: (){deleteEquipo(index: index);}, style: TextButton.styleFrom(backgroundColor: AppTheme.dangerColor)),
TextButton(child: Icon(Icons.edit, color: Color.fromARGB(255, 255, 255, 255)), onPressed: (){}, style: TextButton.styleFrom(backgroundColor: AppTheme.primaryColor)),
TextButton(child: Icon(Icons.qr_code, color: Color.fromARGB(255, 255, 255, 255)), onPressed: (){}, style: TextButton.styleFrom(backgroundColor: AppTheme.primaryBulmaColor)),
],
),
];
});
}
List<Widget> initWidgetDates({required int index}){
List<Widget> widgetDates = [];
for (var i = 0; i < datesOfEquipos[index].length; i++) {
widgetDates.add(CustomDatePickerField(hintText: "Fecha", labelText: "Fecha", onSelectedDate: (date){setState(() {
datesOfEquipos[index][i] = date.toString();
});}, value: datesOfEquipos[index][i],));
}
return widgetDates;
}
void addDate({required int index}){
datesOfEquipos[index].add("");
initEquipos(index: index);
setState(() {});
}
void deleteDate({required int index}){
if((datesOfEquipos[index].length - 1) > 0){
datesOfEquipos[index].removeLast();
initEquipos(index: index);
setState(() {});
}
}
void newEquipo() {
int count = equiposCount.length;
equiposCount.add((count+1));
datesOfEquipos.add([""]);
addFormEquipo();
setState(() {});
}
void addFormEquipo(){
setState(() {
formEquipo.add({
"No" : "",
"clave" : "",
"identificador" : "",
"nombre" : "",
"descripcion" : "",
"cantidad" : "",
"categorias_id" : "",
"subcategorias_id" : "",
"precio_unitario" : "",
"tareas_id" : "",
});
});
}
void deleteEquipo({required int index}){
equiposCount.removeAt(index);
formEquipo.removeAt(index);
datesOfEquipos.removeAt(index);
setState(() {});
}
@override
void initState() {
// TODO: implement initState
super.initState();
resetFormContrato();
resetFormFilters();
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text("LicitaciĆ³n"),
bottom: TabBar(
tabs: [
Tab(text: "Contrato"),
Tab(text: "Equipos"),
],
),
),
body: TabBarView(
children: [
SingleChildScrollView(child: Contrato()),
SingleChildScrollView(child: Equipos()),
],
),
persistentFooterButtons: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children:[
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Cancelar"),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.dangerColor,
),
),
ElevatedButton(
onPressed: () {
},
child: Text("Guardar"),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.successColor,
),
),
]
)
],
),
);
}
Column Contrato() => Column(
children: [
const SizedBox(height: 10),
CustomDropDownCustom1(
message: "Selecciona Empresa",
formValues: formContrato,
formProperty: "Empresa",
heightOfSizedBox: 20,
),
CustomDropDownCustom1(
message: "Selecciona Cliente",
formValues: formContrato,
formProperty: "Cliente",
heightOfSizedBox: 20,
),
CustomDropDownCustom1(
message: "Selecciona Periodicidad",
formValues: formContrato,
formProperty: "Periodicidad",
heightOfSizedBox: 20,
),
CustomDropDownCustom1(
message: "Selecciona Sucursal",
formValues: formContrato,
formProperty: "Sucursal",
heightOfSizedBox: 20,
),
CustomDatePickerField(
hintText: "Fecha",
labelText: "Fecha",
heightOfSizedBox: 20,
onSelectedDate: (date){
}),
CustomInputField(
formProperty: "clave",
formValues: formContrato,
hintText: "Clave",
labelText: "Clave",
onlyLettersAndNumbersNoSpaces: true,
),
CustomInputField(
formProperty: "nombre",
formValues: formContrato,
hintText: "Nombre",
labelText: "Nombre",
onlyLettersAndNumbersNoSpaces: true,
),
CustomInputField(
formProperty: "monto",
formValues: formContrato,
hintText: "Monto",
labelText: "Monto",
onlyNumber: true,
keyboardType: TextInputType.number,
minValueInt: 1,
),
CustomInputField(
formProperty: "descripcion",
formValues: formContrato,
hintText: "Descripcion",
labelText: "Descripcion",
onlyLettersAndNumbersNoSpaces: true,
maxLines: 3,
),
],
);
Column Equipos() => Column(
children: [
Filters(),
PrintVARS(),
newEquipoButton(),
if(equiposCount.length != 0)...[
TableOfEquipos()
],
],
);
TextButton PrintVARS() {
return TextButton(onPressed: (){
print("CONTADOR EQUIPOS ----> $equiposCount");
print("FORM EQUIPOS ----> $formEquipo");
print("FORM EQUIPOS ----> $formEquipo");
print("DATESOFEQUIPOS ----> $datesOfEquipos");
}, child: Text("TEST PRINT"));
}
SingleChildScrollView TableOfEquipos(){
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
dataRowHeight: 270,
columns: [
for(var text in columnsName)...[
DataColumn(label: Text("$text", textAlign: TextAlign.center)),
]
],
rows: [
for (var equipo in equiposCount)...[
DataRow(
cells: [
for(var i = 0; i < columnsWidth.length; i++)...[
DataCell(
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: columnsWidth[i],
child: widgetOfTable(index: equiposCount.indexOf(equipo), indexOfWidget: i)
)
],
)
),
],
]
),
],
]
)
);
}
TextButton newEquipoButton() {
return TextButton.icon(
onPressed: () {
newEquipo();
},
icon: Icon(Icons.add),
label: const Text("Nuevo Equipo"),
style: TextButton.styleFrom(
backgroundColor: AppTheme.primaryColor,
foregroundColor: Colors.white),
);
}
Form Filters() {
return Form(
key: _formKey,
child: ExpansionTile(
title: Text("Filtros"),
children: [
const SizedBox(height: 5),
CustomInputField(
formProperty: "clave",
formValues: formFilterValues,
hintText: "Clave",
labelText: "Clave",
onlyNumber: true,
keyboardType: TextInputType.number,
),
CustomInputField(
formProperty: "identificador",
formValues: formFilterValues,
hintText: "Identificador",
labelText: "Identificador",
),
CustomInputField(
formProperty: "nombre",
formValues: formFilterValues,
hintText: "Nombre",
labelText: "Nombre",
),
CustomInputField(
formProperty: "descripcion",
formValues: formFilterValues,
hintText: "Descripcion",
labelText: "Descripcion",
),
CustomDropDownCustom1(
message: "Seleccione categorias",
formValues: formFilterValues,
formProperty: "active",
items: {
"1": "Activo",
"0": "Inactivo",
},
),
CustomDropDownCustom1(
message: "Seleccione subcategorias",
formValues: formFilterValues,
formProperty: "active",
items: {
"1": "Activo",
"0": "Inactivo",
},
),
ButtonsOfFilters()
],
),
);
}
Row ButtonsOfFilters(){
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton.icon(
onPressed: () {
},
icon: Icon(Icons.search),
label: const Text("Buscar"),
style: TextButton.styleFrom(
backgroundColor: AppTheme.primaryColor,
foregroundColor: Colors.white),
),
TextButton.icon(
onPressed: () {
},
icon: Icon(Icons.clear),
label: const Text("Limpiar"),
style: TextButton.styleFrom(backgroundColor: AppTheme.dangerColor,foregroundColor: Colors.white),
),
],
);
}
Widget widgetOfTable({required int index, required int indexOfWidget}) {
initEquipos(index: index);
return rowsEquipos[indexOfWidget];
}
}
i tried, use a chatgpt and github coopilot and dont work :(
Wrap SingleChildScrollView
with SizedBox
to define fixed height for scroll area.
SizedBox(
height: 200,
child: SingleChildScrollView(
child: Column(
children: [...]
),
),
)