How to get a value from class in StatefulWidget in flutter? - flutter

I am new in flutter and i have some codes to build textfield. i want to make an initial value in textfield but this is from input in another class.
class TextFieldEdit extends StatefulWidget {
TextFieldEdit({
Key? key,
required this.title,
required this.hintTxt,
required this.controller,
required this.defaultTxt,
}) : super(key: key);
final String title, hintTxt;
final controller;
final defaultTxt;
#override
State<TextFieldEdit> createState() => _TextFieldEditState();
}
class _TextFieldEditState extends State<TextFieldEdit> {
TextEditingController _controller = TextEditingController();
#override
void initState() {
super.initState();
_controller.text = defaultTxt;
}
#override
Widget build(BuildContext context) {
return ...
}
in _TextFieldEditState class at the _controller.text i want to get value from defaultTxt in TextFieldEdit class. But how can i send it to _TextFieldEditState class?
the error message is : Undefined name 'defaultTxt'.
Try correcting the name to one that is defined, or defining the name.

Use widget. to access to the variable in constructor:
#override
void initState() {
super.initState();
_controller.text = widget.defaultTxt;
}

To access the widget variable follow widget.variableName
You can do
late final TextEditingController _controller =
TextEditingController.fromValue(
TextEditingValue(text: widget.defaultTxt));
Or use initState to assign the _controller.

Related

Update TextEditingController Text with Riverpod

I'm new to Riverpod and am trying to migrate an app over from Provider. If I had a TextField and wanted to set its value based on my Provider model, I would do this:
class MyWidget extends StatefulWidget{
const MyWidget({ Key? key }) : super(key: key);
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
var controller = TextEditingController();
#override
void didChangeDependencies() {
super.didChangeDependencies();
//Set the value here...
var model = Provider.of<Model>(context);
controller.text = model.name;
}
Widget build(BuildContext context) {
return TextField(controller: controller)
}
}
As I understand it, didChangeDependencies() would listen to changes from Provider.of<Model>(context) and update my controller accordingly.
I'm trying to pull off the same thing with Provider, but I can't ever get the TextField's value to show up.
class MyWidget extends ConsumerStatefulWidget {
const MyWidget({Key? key}) : super(key: key);
#override
ConsumerState<ConsumerStatefulWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends ConsumerState<MyWidget> {
var controller = TextEditingController();
#override
void didChangeDependencies() {
super.didChangeDependencies();
//Trying the same thing here...
final name = ref.watch(providerName);
controller.text = name;
}
Widget build(BuildContext context) {
final name = ref.watch(providerName);
return Column(
children: [
//This doesn't work:
TextField(controller: controller),
//I know my provider has the value, because this works fine:
Text(name),
]
}
}
How can I get my TextEditingController's text property to update?
From Riverpod official website
///1.Create a [StateNotifier] sub-class, StateNotifier is something where you can define functions that can change your state like in this state is of String type, you also can use objects (Classes instead of primitive types)
class Counter extends StateNotifier<String> {
Counter() : super('');
void changeText(String text){
state=text;
}
///2.Create a provider [StateNotifierProvider] with this you can use in your widget
final counterProvider = StateNotifierProvider<Counter, String>((ref) {
return Counter();
});
///3.Consume the Provider this is how we can attach state with our widget
class Home extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final text = ref.watch(counterProvider);
return Text('$text');
}
}
so here you can add you widget like button and onTap executes the code like
onTap()=>changeText(textController.text);
So your text [Text('$text');] will automatically change.
String inputText = controller.text;

default texteditingcontroller for custom text field widget

I want a default empty controller for my custom text field but its not allowing with both ways
You cannot have a const constructor and use a non constant default value.
Therefore you would have to remove the const keyword before CustomTextField. But you can also not have a non-constant value as an optional parameter.
So a suggestion is to change the stateless widget to a stateful widget and initialize the controller in the init() method if no controller is provided with the the contructor.
It's better to set a default controller like this, so we can dispose it to prevent memory leaks:
import 'package:flutter/material.dart';
class CustomTextField extends StatefulWidget {
const CustomTextField({
Key? key,
this.controller,
}) : super(key: key);
final TextEditingController? controller;
#override
State<CustomTextField> createState() => _CustomTextFieldState();
}
class _CustomTextFieldState extends State<CustomTextField> {
late TextEditingController _controller;
#override
void initState() {
super.initState();
_controller = widget.controller ?? TextEditingController();
}
#override
void dispose() {
if (widget.controller == null) {
// if we made the controller ourselves, we dispose it ourselves
// but if it's made outside of this widget, it should be disposed outside
_controller.dispose();
}
super.dispose();
}
#override
Widget build(BuildContext context) {
return Container();
}
}

LateInitializationError: Field 'authProvider' has not been initialized

I got the error LateInitializationError: Field 'authProvider' has not been initialized. for the following:
class HomePage extends StatefulWidget {
HomePage({Key? key}) : super(key: key);
#override
State createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
final FirebaseMessaging firebaseMessaging = FirebaseMessaging.instance;
final ScrollController listScrollController = ScrollController();
late AuthProvider authProvider;
String? currentUserId;
late MainProvider mainProvider;
Debouncer searchDebouncer = Debouncer();
StreamController<bool> btnClearController = StreamController<bool>();
TextEditingController searchBarTec = TextEditingController();
#override
void initState() {
super.initState();
mainProvider = context.read<MainProvider>();
if (authProvider.getUserFirebaseId()!.isNotEmpty == true) {
currentUserId = authProvider.getUserFirebaseId()!;
} else {
return null;
}
registerNotification();
listScrollController.addListener(scrollListener);
}
//more code below
This code is from a Demo: Chat App with Flutter
How do I initialize the fields for authProvider, mainProvider etc?
Late initialization error means that a variable marked as late (in your case authProvider) was not initialized before it was accessed.
on a widget the first thing you execute is the constructor and then you execute the initstate. your constructor has nothing and initstate reads authProvider.getUserFirebaseId().
If you take a look at the video's github page, you will see that before calling authProvider, they initialize it by running the following line:
authProvider = context.read<AuthProvider>();
homeProvider = context.read<HomeProvider>();
If you are following a tutorial, the tutorial is either outdated or not complete if it has this sort of error.

Uri.parse('https://www.a2rstore.in/api/school/v1/noticeApi.php?id=${widget.s_id}'); got error on widget.s_id

class Notice extends StatefulWidget {
final String s_id;
const Notice({Key key, this.s_id}) : super(key: key);
#override
_NoticeState createState() => _NoticeState();
}
class _NoticeState extends State<Notice> {
TextEditingController _titleController = new TextEditingController();
var api =
Uri.parse('https://www.a2rstore.in/api/school/v1/noticeApi.php?id=${widget.s_id}');
You can't call the "widget" without the context.
The proper way to do it is by first defining your variable:
class _NoticeState extends State<Notice> {
TextEditingController _titleController = new TextEditingController();
var api;
...
}
And then assigning to it the value either in the build or initState method:
#override
initState(){
api = Uri.parse('https://www.a2rstore.in/api/school/v1/noticeApi.php?id=${widget.s_id}');
}

Stateful widget, class marked #immutable

I got a Visual Studio warning on my class (below) saying "This class (or a class which this class inherits from) is marked as '#immutable', but one or more of its instance fields are not final: UserSignIn._email", but I cannot mark this argument as final because I initialise it in the constructor
Without final :
class UserSignIn extends StatefulWidget {
TextEditingController _email;
UserSignIn({String emailInput}) {
this._email = TextEditingController(text: (emailInput ?? ""));
}
#override
_UserSignInState createState() => _UserSignInState();
}
class _UserSignInState extends State<UserSignIn> {
#override
Widget build(BuildContext context) {
...
}
}
How to do this ?
Thank you
You should put the TextEditingController in the state class and initialise it in the initState method, like this.
And keep in mind that the StatefulWidget can be different every time when the widget tree is changed, so don't put anything in there that is not immutable.
Keep everything dynamic in the State class
class UserSignIn extends StatefulWidget {
final String emailInput;
const UserSignIn({Key key, this.emailInput}) : super(key: key);
#override
_UserSignInState createState() => _UserSignInState();
}
class _UserSignInState extends State<UserSignIn> {
TextEditingController _controller;
#override
void initState() {
_controller = TextEditingController(text: widget.emailInput);
super.initState();
}
...
}