I have two files, in the first are a few TextformFields and in the second are buttons. I wanna disable the button when one of the TextformFields is empty.
File 1:
class FormTextState extends State<FormText>{
final TextEditingController inputController1 = TextEditingController();
final TextEditingController inputController2 = TextEditingController();
final TextEditingController inputController3 = TextEditingController();
bool submit1 = false;
bool submit2 = false;
bool submit3 = false;
#override
void initState(){
super.initState();
inputController1.addListener(() { setState(() {
submit1 = inputController1.text.isNotEmpty;
});
});
inputController2.addListener(() { setState(() {
submit2 = inputController2.text.isNotEmpty;
});
});
inputController3.addListener(() { setState(() {
submit3 = inputController3.text.isNotEmpty;
});
});
}
#override
void dispose(){
inputController1.dispose();
inputController2.dispose();
inputController3.dispose();
super.dispose();
[...]
}
For each TextFormField the controller is defined as following:
TextFormField(
controller: inputController1,
If I would create the button directly in this file, everything works fine like that:
ElevatedButton(
onPressed: submit1 && submit2 && submit3 ? () => doSomething() : null,
How can I reach this result from the other file with the buttons? The submit values are not reachable. I imported the file at the beginning, of course.
You could add a function to your class like:
class FormTextState extends State<FormText>{
final Function(String str) stringHandler;
...
and when creating the class
FormTextState(stringHandler: _handler);
Future<void> _handler(String str) async {
print(str);
}
you nee to use the following porperties
autovalidateMode: AutovalidateMode.onUserInteraction
onChanged: (val) {
if (formKey.currentState?.validate() == true) {
BlocProvider.of<MyDataBloc>(context)
.add(ActivateButtonEvent());
} else {
BlocProvider.of<MyDataBloc>(context)
.add(DeActivateButtonEvent());
}
},
this will work for formtextfield in case that you are using bloc
Related
i am trying to load api data in init state with provider ,but this error is throwing,i wrapped parent widget with multiprovider and added changenotifier provider also, seems like some error with context of provider but i coudnt find the issue
bool isPostdataloading = false;
bool iscommentsLoading = false;
List<CommentsModelData> commentsCollections = [];
List<SingleUserPostModelData> userPostCollections = [];
#override
void initState() {
super.initState();
getpostdata();
getComments();
}
getpostdata() async {
setState(() {
isPostdataloading = true;
});
userPostCollections =
await SingleUserPostService().getSingleuserPost(postid: widget.postid);
print(userPostCollections[0].commentCount);
setState(() {
isPostdataloading = false;
});
}
getComments() async {
setState(() {
iscommentsLoading = true;
});
commentsCollections =
Provider.of<CommentPageProvider>(context).loadComments(widget.postid);
// commentsCollections =
// await CommentService().getCommentsdata(post_id: widget.postid);
// print(commentsCollections[0].status);
setState(() {
iscommentsLoading = false;
});
}
#override
Widget build(BuildContext context) {
TextEditingController commentTextEditingController =
TextEditingController();
return ChangeNotifierProvider<CommentPageProvider>(
create: (context) => CommentPageProvider(),
child: Scaffold(
bottomNavigationBar: postcomment(widget.postid),
This error happened because you used context that related to the parents of ChangeNotifierProvider, try put your functions inside addPostFrameCallback:
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
getpostdata();
getComments();
});
}
I want to update a list of type SongModel when I enter a value in the TextField. However, the list is not updating when onChanged is called.
List<SongModel> songs = item.data!;
List<SongModel> filterSongs = [];
//showing the songs
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
keyboardType: TextInputType.text,
controller: searchController,
onChanged: (value) {
//pass value for the search
getSearch(filterSongs,songs);
},
decoration: InputDecoration(............
getSearch() :
getSearch(List<SongModel> filterSongs,List<SongModel> songs)
{
var text = searchController.text;
if (text.isEmpty) {
setState(() {
filterSongs = songs;
});
}
print(songs.where((SongModel item) => item.title.toLowerCase().contains(text.toLowerCase())).toList());
print(text);
setState(() {
// search = text;
filterSongs = songs.where((SongModel item) => item.title.toLowerCase().contains(text.toLowerCase())).toList();
});
print(filterSongs.length);
}
Here the list is not updating with set state method.
In your getSearch method, you are setting the value of the parameter passed to getSearch, not the value of the list outside of that method. You should move the filterSongs list declaration outside of your build method anyways so that it isn't redeclared every time the screen is rebuilt.
class MyScreenClassState extends State<MyScreenClass>{
//Create State method here
List<SongModel> filterSongs = [];
//Build method here
}
getSearch(List<SongModel> songs)
{
var text = searchController.text;
if (text.isEmpty) {
setState(() {
filterSongs = songs;
});
}
print(songs.where((SongModel item) => item.title.toLowerCase().contains(text.toLowerCase())).toList());
print(text);
setState(() {
// search = text;
filterSongs = songs.where((SongModel item) => item.title.toLowerCase().contains(text.toLowerCase())).toList();
});
print(filterSongs.length);
}
If onChanged method doesn't work for your implementation, you can try this structure I think I will work for you.
final TextEditingController _controller = TextEditingController();
#override
void initState() {
super.initState();
_controller.addListener(_onControllerChange);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
void _onControllerChange() async {
.....
}
Hey I am a newbie in flutter, I am trying to build an interview radio app
The issue I am facing is when changing state on switching music from one station to another, the "playing" and icon still don't change for the previously clicked object, but the new station starts playing
Here the station has switched but playing text has not yet gone, as well as the icon changed
Ideally, I want when switched, the playing and icon change should be switched to the one playing now, and one that's switched from should have icon showing as the rest
My code
class ItemWidget extends StatefulWidget {
final Item item;
ItemWidget({Key? key, required this.item}) : super(key: key);
#override
State<ItemWidget> createState() => _ItemWidgetState();
}
class _ItemWidgetState extends State<ItemWidget> {
static AudioPlayer player = AudioPlayer();
static String name = "";
static bool isPlaying = false;
static String error = '';
initRadioPlayer(namepassed, url) async {
try {
if (name == namepassed) {
player.stop();
name = "";
isPlaying = false;
setState(() {});
} else if (name != namepassed) {
if (isPlaying == true) {
await player.stop();
}
await player.setUrl(url);
player.play();
name = namepassed;
isPlaying = true;
setState(() {});
}
} catch (err) {
error = err.toString();
setState(() {});
}
}
#override
Widget build(BuildContext context) {
return Card(
child: ListTile(
onTap: () {
initRadioPlayer(widget.item.name, widget.item.url);
},
title: Text(widget.item.name),
subtitle: name == widget.item.name
? isPlaying
? Text('Playing')
: Text('')
: Text(''),
trailing: Icon(isPlaying
? name == widget.item.name
? CupertinoIcons.stop_circle
: CupertinoIcons.play_circle
: CupertinoIcons.play_circle),
textColor: Color.fromARGB(255, 31, 22, 22),
),
);
}
}
I used a callback function and kept the state of which one is playing in the parent just like Ivo Becker suggested:
void _update(String name, bool isPlaying) {
setState(() {
_name = name;
_isPlaying = isPlaying;
});
}
This goes in the parent and then is passed on to and called from the child:
class ItemWidget extends StatefulWidget {
final Item item;
final String name;
final bool isPlaying;
Function callback;
and on tap you call it:
widget.callback(station_name, true);
I'm trying to pass a value of a variable from a StatefulWiget to another StatefulWidget
class InputFieldCheckTick extends StatefulWidget {
double timbreFiscaleFournisseur = 0.000;
bool exoTVA = false;
.
.
.
value: isTicked,
onChanged: (value) async {
await setState(() {
isTicked = value;
if (isTicked == false) {
widget.exoTVA = false;
} else {
widget.exoTVA = true;
}
});
.
.
.
value: isTicked,
onChanged: (value) async {
await setState(() {
isTicked = value;
if (isTicked == false) {
widget.exoTVA = false;
} else {
widget.exoTVA = true;
}
});
and i'm trying to pass the values of exoTVA and timbreFiscaleFournisseur here :
setState(() {
future = ajoutFournisseur(
numeroFournisseur.text,
addressFournisseur.text,
matriculeFiscaleFournisseur.text,
raisonSocialeFournisseur.text,
paysFournisseur.text,
villeFournisseur.text,
InputFieldCheckTick()
.timbreFiscaleFournisseur,
InputFieldCheckTick().exoTVA);
});
I think you are creating an StatefulWidget which contains a Final property called exoTVA, something like:
class MyWidget extends StatefulWidget {
final bool exoTVA;
[...]
Because you are calling widget.exoTVA which refers to stateful related widget, and there is your mistake. You can't change widget.exoTVA for the way widgets are build. What you can do is to do this:
class _MyWidgetState extends State<MyWidget> {
// Here you designate an instance value for your widget property
bool? _exoTVA;
// On initState you define from parent widget, I do this all the time
#override
initState((){
super.initState();
_exoTVA = widget.exoTVA;
});
[...] //Continue with the rest of your widget
Also when you call those changes in setState, change widget.exoTVA to _exoTVA, and to finish you can call that var like this:
setState(() {
future = ajoutFournisseur(
numeroFournisseur.text,
addressFournisseur.text,
matriculeFiscaleFournisseur.text,
raisonSocialeFournisseur.text,
paysFournisseur.text,
villeFournisseur.text,
InputFieldCheckTick()
.timbreFiscaleFournisseur,
_exoTVA);//Changed this line
});
For your reference, check out StatefulWidget class
I am pulling data from Firestore and Editing, and when I click on the data to edit, I don't see it showing anything, however when I write the information and Save. Instead of changing the Edited Field, I get a new document with the edited field.
For example in the code, I edit the name => I will have a new document with the email reused and name changed.
And here is my code:
class EditHouse extends StatefulWidget {
final House house;
EditHouse(this.house);
class _EditHouseState extends State<EditHouse> {
final nameController = TextEditingController();
final emailController = TextEditingController();
#override
void dispose() {
nameController.dispose();
emailController.dispose();
super.dispose();
}
#override
void initState() {
if (widget.house == null) {
nameController.text == "";
emailController.text == "";
new Future.delayed(Duration.zero, () {
final houseProvider =
Provider.of<HouseProvider>(context, listen: false);
houseProvider.loadValues(House(
name: '',
email: ''));
});
} else {
nameController.text = widget.house.name;
emailController.text = widget.house.email;
new Future.delayed(Duration.zero, () {
final houseProvider =
Provider.of<HouseProvider>(context, listen: false);
houseProvider.loadValues(widget.house);
});
}
super.initState();
}}
I don't know if the problem lies here or not EditHouse(this.house);
when I can't use it EditHouse([required this.house]); I will get an error message Can't have modifier 'required' here