Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
289 views
in Technique[技术] by (71.8m points)

flutter - TextField and DatePicker are providing null values

I'm trying to make a todoApp and in my Add Screen there are a textfield for the title of the task and a DatePicker for the date of the task. I think everything is ok in the code cause there isnt any errors but when I click on the Add button, it creates a TaskTile with empty title and empty date. I debugged the code and it seems that the value that I provide in the Provider with the Add Button are empty. It's like what I type is deleted and what i choose in the datepicker is removed. Here's the code of my AddScreen.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'task_data.dart';

import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';

class AddTaskScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
String newTaskTitle;
DateTime _chosenDateTime;
DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss");
String formatedDate;

void _showDatePicker(ctx) {
  
  showCupertinoModalPopup(
      context: ctx,
      builder: (_) => Container(
            height: 500,
            color: Color.fromARGB(255, 255, 255, 255),
            child: Column(
              children: [
                Container(
                  height: 400,
                  child: CupertinoDatePicker(
                      initialDateTime: DateTime.now(),
                      onDateTimeChanged: (val) {
                        // setState(() {
                        //   _chosenDateTime = val;
                        // });
                        _chosenDateTime = val;
                        formatedDate = dateFormat.format(_chosenDateTime);
                        // print('this is the selected date $formatedDate');
                        // print(_chosenDateTime);
                      }),
                ),

                // Close the modal
                CupertinoButton(
                  child: Text('OK'),
                  onPressed: () => Navigator.of(ctx).pop(),
                )
              ],
            ),
          ));
}

return Container(
  color: Color(0xff000014),
  child: Container(
    padding: EdgeInsets.all(20.0),
    decoration: BoxDecoration(
      color: Color(0xFF282D3A),
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(20.0),
        topRight: Radius.circular(20.0),
      ),
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        Text(
          'Add Task',
          textAlign: TextAlign.center,
          style: TextStyle(
            fontSize: 30.0,
            color: Colors.purple.shade400,
          ),
        ),
        TextField(
          decoration: InputDecoration(
            border: InputBorder.none,
          ),
          style: TextStyle(color: Colors.white),
          autofocus: true,
          textAlign: TextAlign.center,
          onChanged: (newText) {
            newTaskTitle = newText;
          },
        ),
        
        Container(
          child: CupertinoButton(
            padding: EdgeInsetsDirectional.zero,
            child: Text('Select a date'),
            onPressed: () => _showDatePicker(context),
          ),
        ),
        FlatButton(
          child: Text(
            'Add',
            style: TextStyle(
              color: Colors.white,
            ),
          ),
          color: Colors.purple.shade400,
          onPressed: () {
            //print('newtasktile is $newTaskTitle et formateddate is $formatedDate');// here the two //values are null when printed
            Provider.of<TaskData>(context,listen: false )
                .addTask(newTaskTitle, formatedDate);
            Navigator.pop(context);
          },
        ),
      ],
    ),
  ),
);
}
}

If you have any suggestions please tell me. Thanks.

question from:https://stackoverflow.com/questions/65928317/textfield-and-datepicker-are-providing-null-values

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

First of all, to conveniently use the value of TextField, you should use TextEditingController. To get the value after selecting a datetime, you can return a value from the Dialog method, then send that value to Stream

Working code (I'm creating a simple UI with simple StreamController to demonstrate):

// TaskData class
class TaskData {
  final StreamController _controller =
      StreamController<Map<String, dynamic>>();

  Stream<Map<String, dynamic>> get taskStream => _controller.stream;

  addTask(String title, String date) {
    _controller.add({'title': title, 'date': date});
  }
}

// AddTask screen
class AddTaskScreen extends StatefulWidget {
  @override
  _AddTaskScreenState createState() => _AddTaskScreenState();
}

class _AddTaskScreenState extends State<AddTaskScreen> {
  final _textController = TextEditingController();
  DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss");
  String chosenDate;
  
  Future<String> _showDatePicker(ctx) async {
      var formatedDate = DateTime.now();
      return showCupertinoModalPopup(
          context: ctx,
          builder: (_) => Container(
                height: 500,
                color: Color.fromARGB(255, 255, 255, 255),
                child: Column(
                  children: [
                    Container(
                      height: 400,
                      child: CupertinoDatePicker(
                          initialDateTime: DateTime.now(),
                          onDateTimeChanged: (val) {
                            formatedDate = val;
                          }),
                    ),

                    // Close the modal
                    CupertinoButton(
                      child: Text('OK'),

                      // Return the formatted date here
                      onPressed: () => Navigator.of(ctx)
                          .pop(dateFormat.format(formatedDate)),
                    )
                  ],
                ),
              ),
          );
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(

          // ... other lines

          child: Column(
              
              // ... other lines

              TextField(
                // Use the _textController here
                controller: _textController,
                decoration: InputDecoration(
                  border: InputBorder.none,
                ),
                style: TextStyle(color: Colors.white),
                autofocus: true,
                textAlign: TextAlign.center,
              ),
              Container(
                child: CupertinoButton(
                  padding: EdgeInsetsDirectional.zero,
                  child: Text('Select a date'),
                  onPressed: () async {
                    // Wait for the return value
                    chosenDate = await _showDatePicker(context);
                  },
                ),
              ),
              FlatButton(
                child: Text(
                  'Add',
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
                color: Colors.purple.shade400,
                onPressed: () {
                  Provider.of<TaskData>(context, listen: false)
                      .addTask(_textController.text, chosenDate);
                  Navigator.pop(context);
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// Main UI Screen
class SomeScreen extends StatefulWidget {
  @override
  _SomeScreenState createState() => _SomeScreenState();
}

class _SomeScreenState extends State<SomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              FlatButton(
                  onPressed: () async {
                    await showDialog(
                        context: context,
                        builder: (context) => AddTaskScreen());
                    setState(() {});
                  },
                  child: Text('Add Task')),
              Container(
                  child: StreamBuilder<Map<String, dynamic>>(
                initialData: {},
                stream: Provider.of<TaskData>(context).taskStream,
                builder: (context, snapshot) {
                  if (!snapshot.hasData) return Container();
                  return Column(
                    children: [
                      Text(
                          '${snapshot.data['title']} | ${snapshot.data['date']}'),
                    ],
                  );
                },
              )),
            ],
          ),
        ),
      ),
    );
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...