sky developer
sky developer

Reputation: 57

Error Get Value TextEditingController In Flutter

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.

Error Log

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

Answers (2)

bluenile
bluenile

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

rickimaru
rickimaru

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

Related Questions