Reputation: 57
I want to retrieve the value from textEditingController with a loop, the problem that occurs when the listview is not scrolled will result in an error, "RangeError (index): Invalid value: Not in inclusive range 0..23: 24", I have random data of 40 records, the application will run properly when scrolling to the end of the line. I want even though I don't scroll down the data can still be retrieved without error.
you can run my sample code, please help me thanks.
import 'dart:math';
import 'package:flutter/material.dart';
class Karyawan {
int id;
String nama;
int jamKerja;
Karyawan({this.id, this.nama,});
Karyawan.fromJson(Map<String, dynamic> json) {
id = json['id'];
nama = json['nama_karyawan'];
jamKerja = json['jam_kerja'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['nama_karyawan'] = this.nama;
data['jam_kerja'] = this.jamKerja;
return data;
}
}
List<Karyawan> _daftarKaryawan = List.generate(
40,
(index) => Karyawan(
id: Random().nextInt(100),
nama: 'test ${Random().nextInt(100)}',
),
);
class FormInputAbsenV3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Entry Absen"),
),
body: FormEntry(listKaryawan:_daftarKaryawan)
);
}
}
class FormEntry extends StatefulWidget {
final List<Karyawan> listKaryawan;
const FormEntry({Key key, this.listKaryawan}) : super(key: key);
@override
_FormEntryState createState() => _FormEntryState();
}
class _FormEntryState extends State<FormEntry> {
List karyawan = [];
final _formKey = GlobalKey<FormState>();
List<TextEditingController> _brutos = new List();
List<TextEditingController> _nettos = new List();
void addlistAbsen() {
for (int i = 0; i < widget.listKaryawan.length; i++) {
karyawan.add({
"id": widget.listKaryawan[i].id,
"bruto": _brutos[i].text,
"netto": _nettos[i].text
});
}
print(karyawan);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.all(5.0),
child: Form(
key: _formKey,
child: Container(
child: ListView.builder(
itemCount: widget.listKaryawan.length,
itemBuilder: (context,index) {
_brutos.add(new TextEditingController());
_nettos.add(new TextEditingController());
return Column(
children: [
FormWidget(
index: index,
nama: widget.listKaryawan[index].nama,
brucon: _brutos[index],
netcon: _nettos[index],
),
SizedBox(
height: 20.0,
),
],
);
},
),
),
),
),
floatingActionButton: FloatingActionButton.extended(
icon: Icon(Icons.save),
label: Text("Save"),
onPressed: () {
if (_formKey.currentState.validate()) {
addlistAbsen();
}
},
),
);
}
}
class FormWidget extends StatelessWidget {
final int index;
final String nama;
final brucon;
final netcon;
FormWidget({this.index, this.nama, this.brucon, this.netcon});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text("${index + 1}. ${nama}"),
),
Expanded(
child: TextFormField(
decoration: new InputDecoration(
labelText: "Bruto",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
),
style: new TextStyle(
fontFamily: "Poppins",
),
controller: brucon,
),
),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
decoration: new InputDecoration(
labelText: "Netto",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
),
style: new TextStyle(
fontFamily: "Poppins",
),
controller: netcon,
))
],
);
}
}
Upvotes: 0
Views: 1277
Reputation: 6029
You CANNOT use ListView.builder for this and you will have to use ListView. You cannot use ListView.builder constructor because the builder is called only for those children that are actually visible. Please see the documentation for ListView.builder
ListView.builder constructor
Creates a scrollable, linear array of widgets that are created on demand.
This constructor is appropriate for list views with a large (or infinite) number of children because the builder is called only for those children that are actually visible.
Please see the following code :
import 'package:flutter/material.dart';
import 'dart:math';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
//theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: FormInputAbsenV3(),
),
),
);
}
}
class Karyawan {
int id;
String nama;
int jamKerja;
Karyawan({
this.id,
this.nama,
});
Karyawan.fromJson(Map<String, dynamic> json) {
id = json['id'];
nama = json['nama_karyawan'];
jamKerja = json['jam_kerja'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['id'] = this.id;
data['nama_karyawan'] = this.nama;
data['jam_kerja'] = this.jamKerja;
return data;
}
}
List<Karyawan> _daftarKaryawan = List.generate(
40,
(index) => Karyawan(
id: Random().nextInt(100),
nama: 'test ${Random().nextInt(100)}',
),
);
class FormInputAbsenV3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Entry Absen"),
),
body: FormEntry(listKaryawan: _daftarKaryawan));
}
}
class FormEntry extends StatefulWidget {
final List<Karyawan> listKaryawan;
const FormEntry({Key key, this.listKaryawan}) : super(key: key);
@override
_FormEntryState createState() => _FormEntryState();
}
class _FormEntryState extends State<FormEntry> {
List karyawan = [];
final _formKey = GlobalKey<FormState>();
List<TextEditingController> _brutos = [];
List<TextEditingController> _nettos = [];
@override
void initState() {
super.initState();
for (int i = 0; i < widget.listKaryawan.length; i++) {
_brutos.add(TextEditingController());
_nettos.add(TextEditingController());
}
}
void addlistAbsen() {
for (int i = 0; i < widget.listKaryawan.length; i++) {
karyawan.add({
"id": widget.listKaryawan[i].id,
"bruto": _brutos[i].text,
"netto": _nettos[i].text
});
}
print(karyawan);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.all(5.0),
child: Form(
key: _formKey,
child: Container(
// child: ListView.builder(
// itemCount: widget.listKaryawan.length,
// itemBuilder: (context, index) {
// _brutos.add(new TextEditingController());
// _nettos.add(new TextEditingController());
// return Column(
// children: [
// FormWidget(
// index: index,
// nama: widget.listKaryawan[index].nama,
// brucon: _brutos[index],
// netcon: _nettos[index],
// ),
// SizedBox(
// height: 20.0,
// ),
// ],
// );
// },
// ),
child: ListView(
children: [
for (int index = 0; index < widget.listKaryawan.length; index++)
Column(
children: [
FormWidget(
index: index,
nama: widget.listKaryawan[index].nama,
brucon: _brutos[index],
netcon: _nettos[index],
),
SizedBox(
height: 20.0,
),
],
),
],
),
),
),
),
floatingActionButton: FloatingActionButton.extended(
icon: Icon(Icons.save),
label: Text("Save"),
onPressed: () {
if (_formKey.currentState.validate()) {
addlistAbsen();
}
},
),
);
}
}
class FormWidget extends StatelessWidget {
final int index;
final String nama;
final TextEditingController brucon;
final TextEditingController netcon;
const FormWidget({this.index, this.nama, this.brucon, this.netcon});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text("${index + 1}. ${nama}"),
),
Expanded(
child: TextFormField(
decoration: InputDecoration(
labelText: "Bruto",
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(),
),
),
style: TextStyle(
fontFamily: "Poppins",
),
controller: brucon,
),
),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
decoration: InputDecoration(
labelText: "Netto",
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(),
),
),
style: TextStyle(
fontFamily: "Poppins",
),
controller: netcon,
))
],
);
}
}
Upvotes: 1
Reputation: 2490
Please initialize your TextEditingControllers during initState.
@override
void initState() {
super.initState();
for (int i = 0; i < widget.listKaryawan.length; i++) {
_brutos.add(new TextEditingController());
_nettos.add(new TextEditingController());
}
}
Then, remove these lines inside the itemBuilder...
_brutos.add(new TextEditingController());
_nettos.add(new TextEditingController());
NOTE: itemBuilder will be called when a list item is to be redisplayed/newly displayed. Therefore, your list of TextEditingControllers > list items. (try scrolling to the bottom most, then scroll back up)
Upvotes: 2