Home > Software design >  I can not save the date after editing in the pop-up box
I can not save the date after editing in the pop-up box

Time:12-30

The code is as follows. All the packages are imported with no error. It adds and saves the text but it does not save the date after editing it in the pop-up box. In the Save part I got this error "Unhandled Exception: type 'bool' is not a subtype of type 'String'". I also tried

Navigator.of(context).pop(textField?.controller?.text ?? "");

but this time it deletes the text after editing and saving it.

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Notepad',
      home: NoteList(),
    );
  }
}

class NoteList extends StatefulWidget {
  @override
  _NoteListState createState() => _NoteListState();
}

class _NoteListState extends State<NoteList> {
  final List<String> _notes = [];
  final TextEditingController _textController = TextEditingController();

  void _loadNotes() async {
    var directory = await getApplicationDocumentsDirectory();
    var file = File("${directory.path}/notes.txt");
    if (!await file.exists()) {
      file.createSync();
      file.writeAsStringSync("Hello, World!\nThis is your first note.\n");
    }
    var contents = await file.readAsString();
    setState(() {
      _notes.addAll(contents.split("\n"));
    });
  }

  void _saveNotes() async {
    var directory = await getApplicationDocumentsDirectory();
    var file = File("${directory.path}/notes.txt");
    var contents = _notes.join("\n");
    await file.writeAsString(contents);
  }

  void _deleteNote(int index) {
    setState(() {
      _notes.removeAt(index);
    });
    _saveNotes();
  }

  @override
  void initState() {
    super.initState();
    _loadNotes();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
        title: Text('Notepad'),
    ),
    body: Column(
    children: [
    Expanded(
    child: ListView.builder(
    itemCount: _notes.length,
    itemBuilder: (context, index) {
    return ListTile(
    title: Text(_notes[index]),
    onTap: () async {
    var result = await showDialog(
    context: context,
    builder: (context) {
    return AlertDialog(
    title: Text("Edit Note"),
    content: TextField(
    controller: TextEditingController(text: _notes[index]),
    autofocus: true,
    ),
    actions: [
    ElevatedButton(
    child: Text("Cancel"),
    onPressed: () => Navigator.of(context).pop(),
    ),
    ElevatedButton(
    child: Text("Save"),
    onPressed: () {
    final TextField? textField = context.findAncestorWidgetOfExactType<TextField>();
    Navigator.of(context).pop(textField != null?.controller?.text);
    },
    ),
    ],
    );
    },
    );
    // update the note with the new text if the user saved their changes
    if (result != null) {
      setState(() {
        _notes[index] = result;
      });
      _saveNotes();
    }
    },
      trailing: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          IconButton(
            icon: Icon(Icons.delete),
            onPressed: () => _deleteNote(index),
          ),
        ],
      ),
    );
    },
    ),
    ),
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: TextField(
          controller: _textController,
          decoration: InputDecoration(
            hintText: "Enter a new note",
          ),
        ),
      ),
      ElevatedButton(
        child: Text("Add Note"),
        onPressed: () {
          setState(() {
            _notes.add(_textController.text);
          });
          _textController.clear();
          _saveNotes();
        },
      ),
    ],
    ),
    );
  }
}

CodePudding user response:

I never used findAncestorWidgetOfExactType before in my code but its for finding the ancestor. But when you are using the AlertDialog, its inner widgets like title, content and actions are suppose to be siblings. Thats why you can't find the TextField using this method.

Try creating a temporary TextEditingController inside the showDialog's builder method & use that in the TextField & Save button. Like this

var result = await showDialog(
      context: context,
      builder: (context) {
          TextEditingController temp = TextEditingController(text: _notes[index]);
          return AlertDialog(
               title: Text("Edit Note"),
               content: TextField(
                   controller: temp,
                   autofocus: true,
                ),
                actions: [
                    ElevatedButton(
                       child: Text("Cancel"),
                       onPressed: () => Navigator.of(context).pop(),
                    ),
                    ElevatedButton(
                        child: Text("Save"),
                        onPressed: () {
                           Navigator.of(context).pop(temp.text);
                        },
                    ),
                 ],
           );
      },
   );                    

You can test the code here https://dartpad.dev/?id=e75b493dae1287757c5e1d77a0dc73f1

  • Related