How should I manage multiple Provider and Consumer - flutter

I'm coding textfield with river_pod library as follows.
When I tapped each suffixIcon, it works both password and password-confirmation field and finally it figured out that each state is only managed by single provider.
And wonder how should I manage this provider and consumer separately, and effectively.
//main.dart
import 'package:cards/view/textfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(
ProviderScope(
child: MaterialApp(
title: 'Cards Demo',
home: RegisterWidget(),
),
),
);
}
class RegisterWidget extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
body: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(20, 50, 20, 0),
child: Column(
children: [
Container(
width: double.infinity,
height: 50,
// color: Colors.grey,
alignment: Alignment.topLeft,
child: Image.asset('images/logo.png'),
),
Container(
padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0),
margin: const EdgeInsets.only(top: 30),
width: double.infinity,
// color: Colors.blue,
child: Column(
children: [
const Align(
alignment: AlignmentDirectional(0, 0),
child: TextFieldCustom(
labelText: "email",
hintText: "type your email-adress",
suffixIcon: null,
),
),
Align(
alignment: const AlignmentDirectional(0, 0),
child: TextFieldCustom(
labelText: "password",
hintText: "set password",
suffixIcon: SuffixIconWidget()),
),
Align(
alignment: const AlignmentDirectional(0, 0),
child: TextFieldCustom(
labelText: "password-confirm",
hintText: "password for confirmation",
suffixIcon: SuffixIconWidget()),
),
],
),
),
],
),
));
}
}
//textfield.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
final mask = StateProvider<bool>((ref) => true);
class TextFieldCustom extends ConsumerWidget {
const TextFieldCustom({required this.labelText, required this.hintText, this.suffixIcon, Key? key}): super(key: key);
final String labelText;
final String hintText;
final Widget? suffixIcon;
#override
Widget build(BuildContext context, WidgetRef ref) {
return Container(
margin: const EdgeInsets.only(bottom: 10),
child: TextFormField(
style: const TextStyle(
fontSize: 13,
),
obscureText: ObscureTextFunction(suffixIcon, ref),
decoration: InputDecoration(
labelText: labelText, //**
hintText: hintText, //**
suffixIcon: suffixIcon, //**
labelStyle: const TextStyle(
fontSize: 15,
color: Color.fromARGB(255, 219, 219, 219),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(2),
borderSide: const BorderSide(
color: Color.fromARGB(255, 219, 219, 219),
width: 1.0,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(2),
borderSide: const BorderSide(
color: Color.fromARGB(255, 219, 219, 219),
width: 1.0, //outlineの太さ
)),
),
));
}
}
bool ObscureTextFunction(suffixIcon, ref) {
if (suffixIcon == null) {
return false;
} else {
final bool isVisible = ref.watch(mask);
return isVisible ? false : true;
}
}
class SuffixIconWidget extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final bool isVisible = ref.read(mask);
return IconButton(
icon: Icon(ref.watch(mask) // false
? FontAwesomeIcons.solidEye
: FontAwesomeIcons.solidEyeSlash),
onPressed: () {
ref.read(mask.notifier).update((state) => !isVisible);
},
);
}
}
Additional Code
final mask = StateProvider<bool>((ref) => true);
final maskConfirm = StateProvider<bool>((ref) => true);
class SuffixIconWidget extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final bool isVisible = ref.read(mask);
return IconButton(
icon: Icon(ref.watch(mask) // false
? FontAwesomeIcons.solidEye
: FontAwesomeIcons.solidEyeSlash),
onPressed: () {
ref.read(mask.notifier).update((state) => !isVisible);
},
);
}
}
class SuffixIconWidgetConfirm extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final bool isVisible = ref.read(maskConfirm);
return IconButton(
icon: Icon(ref.watch(maskConfirm) // false
? FontAwesomeIcons.solidEye
: FontAwesomeIcons.solidEyeSlash),
onPressed: () {
ref.read(maskConfirm.notifier).update((state) => !isVisible);
},
);
}
}

For local states that are only important for the widget, I would just recommend you have a simple boolean in TextFieldCustom and change it with setState.
Generally speaking though, for this widget to be correctly reusable with Riverpod, you should create a callback function onIconPressed(). Just like you are passing labelText, suffixIcon etc., in Flutter you can also pass functions like you do for buttons. Then for one provider to work on both widgets, it shouldn't be a provider of boolean, but instead of an object that holds two booleans.

Related

How to manage a custom widget state in SingleChildScrollView Widget

I'm trying to design this view.
I already have the basic design of the cards, but i would like to know how to change the card's background color, the card's border color and add the little green square according to the width size of the current card when the user click one of them. It's important to know that only one card can be painted in green when the user clicked it.
Here is my code:
CategoryCardModel
class CategoryCardModel {
final String? categoryCardModelName;
CategoryCardModel(this.categoryCardModelName);
}
CategoryCard
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: RoundedRectangleBorder(
side: const BorderSide(
color: Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
MyHomePage
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'category_card.dart';
import 'category_card_model.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// List of models
final categoryCardModelList = <CategoryCardModel>[
CategoryCardModel("Todas"),
CategoryCardModel("Smartphones"),
CategoryCardModel("Accesorios para celular"),
CategoryCardModel("TV")
];
List<CategoryCardModel>? _categoryCardModelListOf;
#override
void initState() {
super.initState();
setState(() {
_categoryCardModelListOf = List.of(categoryCardModelList);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
wasPressed: () {
print("Hello World");
setState(() {});
},
categoryCardName:
categoryCardModel.categoryCardModelName))
.toList())));
}
}
main
import 'package:flutter/material.dart';
import 'my_home_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "Caregory Cards"),
);
}
}
Selected is needed for Card
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool isActive;
const CategoryCard(
{super.key,
required this.categoryCardName,
this.wasPressed,
this.isActive = false});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: const StadiumBorder(),
child: Container(
decoration: BoxDecoration(
color: (isActive ? Colors.green : Colors.grey).withOpacity(.1),
borderRadius: BorderRadius.circular(24.0),
border: Border.all(
width: 2, color: isActive ? Colors.green : Colors.grey)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
Create a state variable for selected model
CategoryCardModel? activeTab;
And use
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
isActive: activeTab == categoryCardModel,
wasPressed: () {
activeTab = categoryCardModel;
setState(() {});
},
categoryCardName: categoryCardModel.categoryCardModelName))
.toList(),
),
Update your CategoryCard class like this, you may need to change the color according to your desire :
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool isSelected;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
this.isSelected = false,
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: isSelected ? Colors.green : Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: isSelected ? Colors.greenAccent : const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0),
),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
And then change your _MyHomePageState class to this :
class _MyHomePageState extends State<MyHomePage> {
// List of models
final categoryCardModelList = <CategoryCardModel>[
CategoryCardModel("Todas"),
CategoryCardModel("Smartphones"),
CategoryCardModel("Accesorios para celular"),
CategoryCardModel("TV")
];
List<CategoryCardModel>? _categoryCardModelListOf;
CategoryCardModel? _selectedCardModel;
#override
void initState() {
super.initState();
setState(() {
_categoryCardModelListOf = List.of(categoryCardModelList);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
wasPressed: () {
print("Hello World");
setState(() {
_selectedCardModel = categoryCardModel;
});
},
categoryCardName: categoryCardModel.categoryCardModelName,
isSelected: _selectedCardModel == categoryCardModel,
))
.toList(),
),
),
);
}
}
Use above two answers for highlighting selected option...and here is what missing...
The underline below selected tab...
for that update your category card as below,
as u have mentioned underline width must be in size of tab width,
I have used ** IntrinsicWidth**
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool? isselected;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
this.isselected=false
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: IntrinsicWidth(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(children: [
Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color:isselected==true?Colors.red: Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
if(isselected==true)
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Container(
color: Colors.red[200],
height: 5,
),
),
],),
),
),
);
}
}

notifying id token listeners about user flutter

543 / 5 000
Résultats de traduction
I'm new to coding and I'm trying to create a login page with firebase but the problem is that when I put my email + my password I have this message that appears 'Ignoring header X-Firebase-Locale because its value was null.
W/System (30113): Ignoring header X-Firebase-Locale because its value was null.
D/FirebaseAuth(30113): Notifying id token listeners about user ( gZ4NEwxh0qRRl32ypTGvqgX6kJx2 ).' I connected firebase to my application and I put the authentication by mail, I added the sha1 and the sha-256.
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
get crossAxisAlignment => crossAxisAlignment;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: FirstPage(),
);
}
}
import 'package:flutter/material.dart';
import'package:firebase_auth/firebase_auth.dart';
import 'package:untitled/connexion.dart';
import 'package:untitled/home.dart';
class MainPage extends StatelessWidget{
const MainPage({Key? key}) : super(key: key);
Widget build(BuildContext context){
return Scaffold(
body:StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData){
return HomePage();
} else{
return LloginScreen1();
}
}
)
);
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:delayed_display/delayed_display.dart';
import 'services/auth.dart';
class LloginScreen1 extends StatefulWidget {
const LloginScreen1({Key? key}) : super(key: key);
#override
State<LloginScreen1> createState() => _LloginScreen1();
}
class _LloginScreen1 extends State<LloginScreen1> {
Authservices auth = Authservices();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _user = FirebaseAuth.instance.idTokenChanges();
Future signIn() async{
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
}
#override
void dispose(){
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Center(
child: DelayedDisplay(
delay: Duration(milliseconds: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(height: 100),
Image.asset(
"images/nutrisport.png", width: 300, height: 200,),
SizedBox(width: 330,
child: TextField(
controller: _emailController,
style: TextStyle(fontSize: 20.0),
decoration: InputDecoration(
prefixIcon: Icon(Icons.email_outlined),
contentPadding: EdgeInsets.fromLTRB(
20.0, 15.0, 20.0, 15.0),
hintText: "Email",
border:
OutlineInputBorder(
borderRadius: BorderRadius.circular(
32.0))),
)
),
SizedBox(height: 10,),
SizedBox(width: 330,
child: TextField(
obscureText: true,
controller: _passwordController,
style: TextStyle(fontSize: 20.0),
decoration: InputDecoration(
suffixIcon: GestureDetector(
child: Icon(
Icons.visibility_off
),
),
prefixIcon: Icon(Icons.lock_outline),
contentPadding: EdgeInsets.fromLTRB(
20.0, 15.0, 20.0, 15.0),
hintText: "Password",
border:
OutlineInputBorder(
borderRadius: BorderRadius.circular(
32.0))),
),
),
SizedBox(height: 50,),
SizedBox(height:55,
width: 330,
child:ElevatedButton(
child: Text('Connexion',style: TextStyle(fontSize: 22),),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Color.fromARGB(
200, 119, 141, 67)),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
)
),
onPressed: signIn,
),),
TextButton(
onPressed: () {},
child: Text('Mot de passe oublié ?',
style: TextStyle(
fontSize: 20,
color: Colors.cyan
),
),
),
])))));
}
}

Pass Value between two class in Flutter

How can pass two String between two class? I have a Signin Class where i have two TextField for email and password. Then I have a Button class but I don't know how get email and password String.
I would not create a single class to keep tidy my code.
This is my code:
SigninClass
import 'package:cleverpot/Activity/home.dart';
import 'package:cleverpot/Helper/authelper.dart';
import 'package:cleverpot/signin/signout/Header.dart';
import 'package:cleverpot/signin/signout/InputField.dart';
import 'package:cleverpot/signin/signout/InputWrapper.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class Signup extends StatefulWidget {
Signup({Key? key}) : super(key: key);
#override
_nameState createState() => _nameState();
}
class _nameState extends State<Signup> {
String email = "";
String password = "";
authHelper _helper = authHelper();
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
colors: [Colors.green, Colors.greenAccent])),
child: Column(
children: [
SizedBox(
height: 80,
),
Header(),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.green[300],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60))),
child: InputWrapper(),
))
],
),
),
);
}
}
InputWrapper Class:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'Button.dart';
import 'InputField.dart';
class InputWrapper extends StatefulWidget {
InputWrapper({Key? key}) : super(key: key);
#override
_InputWrapperState createState() => _InputWrapperState();
}
class _InputWrapperState extends State<InputWrapper> {
String email = '';
String password = '';
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(30),
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10)),
child: InputField(),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
text: "Password dimenticata?",
style: TextStyle(color: Colors.grey),
recognizer: TapGestureRecognizer()
..onTap = () {
print("Cliccato");
})),
SizedBox(
height: 20,
),
Button(),
SizedBox(
height: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green[500],
borderRadius: BorderRadius.circular(50)),
child: RichText(
text: TextSpan(
text: "Non sei registrato? Clicca qua",
style: TextStyle(color: Colors.black),
recognizer: TapGestureRecognizer()
..onTap = () {
Navigator.of(context).push(PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, _, __) {
return Registration();
}));
print("Cliccato");
})),
),
],
),
);
}
InputField Class:
import 'package:flutter/material.dart';
class InputField extends StatefulWidget {
InputField({Key? key}) : super(key: key);
#override
_InputFieldState createState() => _InputFieldState();
}
class _InputFieldState extends State<InputField> {
String password = '';
String email = '';
String getil() {
return password;
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
decoration: InputDecoration(
hintText: "Enter your email",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none),
),
),
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
onChanged: (value) {
setState(() {
password = value;
print(password);
});
},
decoration: InputDecoration(
hintText: "Enter your password",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none),
),
),
],
);
;
}
}
And Button Class:
import 'package:cleverpot/Helper/authelper.dart';
import 'package:cleverpot/signin/signout/InputField.dart';
import 'package:flutter/material.dart';
class Button extends StatelessWidget {
authHelper _helper = authHelper();
#override
Widget build(BuildContext context) {
return Container(
height: 50,
margin: EdgeInsets.symmetric(horizontal: 50),
decoration: BoxDecoration(
color: Colors.cyan[500],
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: ElevatedButton(
onPressed: () {
print(fieldState.getil());
},
child: Text(
"Accedi",
style: TextStyle(
color: Colors.white, fontSize: 15, fontWeight: FontWeight.bold),
),
),
),
);
}
}
I have to get Email and Password from InputField in InputWrapper and put inside Button Class in InputWrapper
You should Lift your state up. This is a general advice in flutter, the state variables should be contained in a stateful widget which is common to every widget you want to share the variables to.
In your case something like this:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class Signup extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter, colors: [Colors.green, Colors.greenAccent])),
child: Column(
children: [
SizedBox(
height: 80,
),
Header(),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.green[300],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60), topRight: Radius.circular(60))),
child: InputWrapper(),
),
),
],
),
),
);
}
}
class InputWrapper extends StatefulWidget {
InputWrapper({Key? key}) : super(key: key);
#override
_InputWrapperState createState() => _InputWrapperState();
}
class _InputWrapperState extends State<InputWrapper> {
String email = '';
String password = '';
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(30),
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Container(
decoration:
BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(10)),
child: InputField(
email: email,
password: password,
onEmailChanged: (value) => setState(() => email = value),
onPasswordChanged: (value) => setState(() => password = value),
),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
text: "Password dimenticata?",
style: TextStyle(color: Colors.grey),
recognizer: TapGestureRecognizer()
..onTap = () {
print("Cliccato");
})),
SizedBox(
height: 20,
),
Button(password: password),
SizedBox(
height: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green[500], borderRadius: BorderRadius.circular(50)),
child: RichText(
text: TextSpan(
text: "Non sei registrato? Clicca qua",
style: TextStyle(color: Colors.black),
recognizer: TapGestureRecognizer()
..onTap = () {
Navigator.of(context).push(
PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, _, __) {
return Registration();
},
),
);
print("Cliccato");
},
),
),
),
],
),
);
}
}
class InputField extends StatelessWidget {
final String email;
final String password;
final void Function(String) onEmailChanged;
final void Function(String) onPasswordChanged;
const InputField({
Key? key,
required this.email,
required this.password,
required this.onEmailChanged,
required this.onPasswordChanged,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration:
BoxDecoration(border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
onChanged: onEmailChanged,
decoration: InputDecoration(
hintText: "Enter your email",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none,
),
),
),
Container(
padding: EdgeInsets.all(10),
decoration:
BoxDecoration(border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
onChanged: onPasswordChanged,
decoration: InputDecoration(
hintText: "Enter your password",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none,
),
),
),
],
);
}
}
class Button extends StatelessWidget {
final String password;
const Button({
Key? key,
required this.password,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 50,
margin: EdgeInsets.symmetric(horizontal: 50),
decoration: BoxDecoration(
color: Colors.cyan[500],
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: ElevatedButton(
onPressed: () {
print(password);
},
child: Text(
"Accedi",
style: TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.bold),
),
),
),
);
}
}

Unhandled Exception: BlocProvider.of() called with a context that does not contain a SignupBloc

I am a beginner in flutter_bloc library pattern, i am trying to signup http post request. I follow all the bloc necessary steps but when i click on Signup button it shows me on the log "Unhandled Exception:BlocProvider.of() called with a context that does not contain a SignupBloc. No ancestor could be found starting from the context that was passed to BlocProvider.of(). This can happen if the context you used comes from a widget above the BlocProvider." Although i have added this Signupbloc in main.dart how to fix this issue.
Main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MultiBlocProvider(providers: [
BlocProvider<RecommendedBloc>(
create: (BuildContext context) => RecommendedBloc(
RecommendedForYouDataService(),
),
),
BlocProvider<CuisineDishesBloc>(
create: (BuildContext context) => CuisineDishesBloc(
BrowseByCuisineDishesDataService(),
),
),
BlocProvider<DetailsBloc>(
create: (BuildContext context) => DetailsBloc(
DetailsDataService(),
),
),
BlocProvider<SearchBloc>(
create: (BuildContext context) => SearchBloc(
AllRestaurantDataService(), SearchRestaurantDataService()),
),
BlocProvider<AllPhotosBloc>(
create: (BuildContext context) =>
AllPhotosBloc(AllPhotosDataService()),
),
BlocProvider<PlacePhotosBloc>(
create: (BuildContext context) =>
PlacePhotosBloc(PlacePhotosDataService()),
),
BlocProvider<FoodPhotosBloc>(
create: (BuildContext context) =>
FoodPhotosBloc(FoodPhotosDataService()),
),
BlocProvider<EventPhotosBloc>(
create: (BuildContext context) =>
EventPhotosBloc(EventPhotosDataService()),
),
BlocProvider<SignupBloc>(
create: (BuildContext context) => SignupBloc(SignUpDataService()),
),
], child: LoginPage()),
);
}
}
SignUpDataService.dart
class SignUpDataService {
Future<SignUp?> makeRequestSignUp(String firstName, String lastName,
String mobileNumber, String password, String gender) async {
var response =
await http.post(Uri.parse('$baseURL/customer/signup'), body: {
"phone_number": mobileNumber,
"password": password,
});
if (response.statusCode == 200) {
final responseString = response.body;
final data = jsonDecode(responseString);
SignUp signUp = SignUp.fromJson(data);
return signUp;
} else {
throw Exception();
}
}
}
Signup_event.dart
#immutable
abstract class SignupEvent {}
class SignUpSubmittedEvent extends SignupEvent {
final String phoneNumber;
final String password;
SignUpSubmittedEvent(this.firstName, this.lastName, this.phoneNumber,
this.password, this.gender);
}
SignupState_state
#immutable
abstract class SignupState {}
class SignupInitialState extends SignupState {}
class SignupLoadingState extends SignupState {}
class SignupSuccessState extends SignupState {
final SignUp data;
SignupSuccessState(this.data);
}
class SignupErrorState extends SignupState {
final String message;
SignupErrorState(this.message);
}
Signup_bloc.dart
class SignupBloc extends Bloc<SignupEvent, SignupState> {
SignUpDataService signUpDataService;
SignupBloc(this.signUpDataService) : super(SignupInitialState());
#override
Stream<SignupState> mapEventToState(
SignupEvent event,
) async* {
if (event is SignUpSubmittedEvent) {
yield SignupLoadingState();
try {
SignUp? signup = await signUpDataService.makeRequestSignUp(
event.phoneNumber,
event.password,
yield SignupSuccessState(signup!);
} catch (e) {
yield SignupErrorState(e.toString());}}}}
Register.dart
class RegisterPage extends StatefulWidget {
const RegisterPage({Key? key}) : super(key: key);
#override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
bool checkOS = Platform.isIOS;
late bool _passwordVisible;
final TextEditingController mobileNumber = TextEditingController();
final TextEditingController password = TextEditingController();
bool _validate = false;
final _formKey = GlobalKey<FormState>();
String pWord = "";
late List<String> menus;
static late int menuIndex;
late SignupBloc signupBloc;
void submitForm() {
final isValid = _formKey.currentState!.validate();
}
#override
void initState() {
_passwordVisible = false;
super.initState();
}
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: TuxedoColor.loginColor,
body: Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: Container(
alignment: Alignment.center,
child: Center(
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
decoration: BoxDecoration(
border:
Border.all(color: TuxedoColor.greyColor),
borderRadius: BorderRadius.all(Radius.circular(
5.0) // <--- border radius here
),
),
child: Padding(
padding: const EdgeInsets.only(
top: 10.0,
bottom: 10.0,
left: 10.0,
right: 5.0),
child: Icon(
Icons.arrow_back_ios,
color: TuxedoColor.greyColor,
),
),
),
),
Text(
'Sign Up',
style: TextStyle(
fontSize: 25.0, fontWeight: FontWeight.bold),
),
GestureDetector(
onTap: () {},
child: Text(
'عربي',
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
)
],
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 35.0),
child: TextFormField(
controller: mobileNumber,
keyboardType: TextInputType.phone,
decoration: new InputDecoration(
fillColor: TuxedoColor.textFieldColor,
filled: true,
hintText: "Mobile Number",
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: TuxedoColor.greyColor)),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: TuxedoColor.greyColor)),
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 30.0),
child: TextFormField(
keyboardType: TextInputType.visiblePassword,
controller: password,
obscureText: !_passwordVisible,
onChanged: (value) => pWord = value,
decoration: new InputDecoration(
suffixIcon: IconButton(
icon: Icon(
_passwordVisible
? Icons.visibility
: Icons.visibility_off,
),
onPressed: () {
setState(() {
_passwordVisible = !_passwordVisible;
});
},
),
fillColor: TuxedoColor.textFieldColor,
filled: true,
hintText: "Password",
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: TuxedoColor.greyColor)),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: TuxedoColor.greyColor))),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0,
right: 15.0,
),
child: ConstrainedBox(
constraints:
BoxConstraints.tightFor(height: height * 0.065),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
TuxedoColor.redColor),
),
onPressed: () async {
submitForm();
final fName = firstName.text;
final lName = lastName.text;
final mNumber = mobileNumber.text;
final pass = password.text;
final gen = gender.toString();
signupBloc = BlocProvider.of<SignupBloc>(context)
..add(SignUpSubmittedEvent(
mNumber, pass)); //On this line getting error
},
child: Text(
'SignUp',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18.0,
color: TuxedoColor.blackColor),
)),
),
),
],
),
)
],
),
),
),
),
),
),
);
}
}
You should swap MaterialApp and MultiBlocProvider.
Bloc provider must be on top of MaterialApp as suggested in this issue by lib creator Felix.

How to clear Flutter Text Field from parent widget

How to clear Flutter Text Field from parent widget
I am a newbie for flutter and dart. I am developing a calculator type application.
I want to clear the text field in the TextFieldContainer1 class from my parent widget Calculator method using method function.
This is the parent widget (Calculator) which contains reset function.
class Calculator extends StatefulWidget {
#override
_CalculatorState createState() => _CalculatorState();
}
class _CalculatorState extends State<Calculator> {
double soldPrice=0.00;
reset(){
soldPrice=0.00;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: BgColor ,
bottomNavigationBar: Container(
decoration: BoxDecoration(
borderRadius:BorderRadius.only(topLeft: Radius.circular(10), topRight:Radius.circular(10) ),
color:YellowBg,
),
alignment: Alignment.center,
height: 50,
child: Text('RESET',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
letterSpacing: 5,
),
),
),
body: SafeArea(
child: Column(
children: <Widget>[
SizedBox(height:10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
EcalLogo(logoSize: 30,),
],
),
SizedBox(height:10),
Padding(
padding:EdgeInsets.symmetric(horizontal:10.0),
child:FractionallySizedBox(
widthFactor: 0.9,
child: Container(
height:1.0,
width:130.0,
color:Colors.white,),
),),
SizedBox(height: 10,),
Expanded(
child:ListView(
children: <Widget>[
TextFieldContainer1(
title: 'SOLD PRICE',
tagLine: "SALE PRICE WITOHUT SHIPPING",
icon: Icons.check_circle,
onChange: (val) => setState(() {
soldPrice = double.parse(val);
})
),
],
))
],
),
)
);
}
}
This is the child widget class(TextFieldContainer1)
class TextFieldContainer1 extends StatefulWidget {
final String title;
final String tagLine;
final IconData icon;
final Function(String) onChange;
// Function displayFunction;
TextFieldContainer1({this.title,this.tagLine,this.icon,this.onChange});
#override
_TextFieldContainer1State createState() => _TextFieldContainer1State();
}
class _TextFieldContainer1State extends State<TextFieldContainer1> {
#override
Widget build(BuildContext context) {
return FractionallySizedBox(
widthFactor: 0.95,
child: Container(
padding: EdgeInsets.symmetric(horizontal:20, vertical:5),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: tileBackground,
),
height: 57,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:<Widget>[
Container(
child:Column(
children:<Widget>[
Row(
children:<Widget>[
Icon(widget.icon,
color:Color.fromRGBO(255, 255, 255, 0.7),
size:20
),
SizedBox(width:15),
Text(widget.title,
style: TextStyle(
fontSize: 20,
color:Colors.white,
fontWeight: FontWeight.w500
),
)
]
),
Text(widget.tagLine,
style: TextStyle(
color:Color.fromRGBO(255, 255, 255, 0.5),
fontSize: 12
),
)
]
)
),
Container(
padding: EdgeInsets.symmetric(horizontal: 15,vertical: 5),
decoration: BoxDecoration(
color: Color.fromRGBO(252, 205, 0, 0.2),
borderRadius: BorderRadius.all(Radius.circular(10)
)
),
height: 40,
width: 92,
child: TextField(
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 20
),
autofocus: false,
decoration:InputDecoration(
focusColor: YellowBg,
fillColor: YellowBg,
hoverColor: YellowBg,
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: YellowBg),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: YellowBg),)
) ,
keyboardType: TextInputType.number,
onChanged: widget.onChange,
),
)
],
),
),
);
}
}
How to clear the text field in the TextFieldContainer1 class from my parent widget Calculator using the reset function?
make your text field accept a controller:
class TextFieldContainer1 extends StatefulWidget {
final String title;
final String tagLine;
final IconData icon;
final Function(String) onChange;
final TextEditingController controller;
// Function displayFunction;
TextFieldContainer1({this.title,this.tagLine,this.icon,this.onChange,
this.controller});
#override
_TextFieldContainer1State createState() => _TextFieldContainer1State();
}
class _TextFieldContainer1State extends State<TextFieldContainer1> {
// also don't forget to dispose the controller
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
and use it in your widget like this:
class Calculator extends StatefulWidget {
#override
_CalculatorState createState() => _CalculatorState();
}
class _CalculatorState extends State<Calculator> {
final _controller = TextEditingController();
double soldPrice=0.00;
reset(){
soldPrice=0.00;
}
#override
Widget build(BuildContext context) {
// ....
TextFieldContainer1(
title: 'SOLD PRICE',
tagLine: "SALE PRICE WITOHUT SHIPPING",
icon: Icons.check_circle,
controller: _controller,
onChange: (val) => setState(() {
soldPrice = double.parse(val);
}),
),
],
))
void reset() => _controller.clear();
// ....