Error Get Value TextEditingController In Flutter

早过忘川 提交于 2021-01-07 01:35:11

问题


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,
            ))
      ],
    );
  }
}

回答1:


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,
        ))
      ],
    );
  }
}



回答2:


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)



来源:https://stackoverflow.com/questions/65432105/error-get-value-texteditingcontroller-in-flutter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!