I have a firestore collection, 'users', that I have a String field 'handle' defined for each document. Id like to be able to query the collection and return a boolean value if the handle is currently used or not.
Im trying to use something like the following:
Future<bool> userExists(String handle) async =>
(await userCollection.where("handle", isEqualTo: handle).get()).docs.length > 0;
However, since this is a future, can i use it to react in the ui following an onChanged call in the textfield? Or do i need to write it as a Stream?
Actual screen code:
import 'package:hero/screens/onboarding/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:step_progress_indicator/step_progress_indicator.dart';
import '../../../models/models.dart';
import '../widgets/custom_onbaording_buttons.dart';
class Handle extends StatefulWidget {
final TabController tabController;
final User user;
const Handle({
Key? key,
required this.tabController,
required this.user,
}) : super(key: key);
@override
State<Handle> createState() => _HandleState();
}
class _HandleState extends State<Handle> {
initState() {
super.initState();
}
String handle = '@';
bool isValid = false;
@override
Widget build(BuildContext context) {
final controller = TextEditingController();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomTextHeader(
tabController: widget.tabController,
text: 'What do you want your handle to be?',
),
SizedBox(height: 10),
CustomTextField(
hint: handle,
initialValue: '@',
onChanged: (val) => setState(() => handle = val),
),
// CustomCheckbox(
],
),
],
),
Column(
children: [
StepProgressIndicator(
totalSteps: 4,
currentStep: 1,
selectedColor: Theme.of(context).primaryColor,
unselectedColor: Theme.of(context).scaffoldBackgroundColor,
),
SizedBox(height: 10),
CustomOnboardingButton(
tabController: widget.tabController,
text: 'NEXT STEP',
id: widget.user.id,
),
],
),
],
),
);
}
}
Thanks!
CodePudding user response:
you can make a method that checks if the handle is valid or not every time the handle value is upgraded and changes the isValid value accordingly,
Future<bool> userExists() async {
bool exist = (await userCollection.where("handle", isEqualTo: handle).get())
.docs
.length >
0;
if (!exist) {
setState(() => isValid = true);
}
}
after that you can use the isValid value in the textfield to show error
decoration: InputDecoration(
errorText: isValid ? null : "Handle already taken",
)
here is the full code(its just a rough idea implement it according to this plan)
import 'package:hero/screens/onboarding/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:step_progress_indicator/step_progress_indicator.dart';
import '../../../models/models.dart';
import '../widgets/custom_onbaording_buttons.dart';
class Handle extends StatefulWidget {
final TabController tabController;
final User user;
const Handle({
Key? key,
required this.tabController,
required this.user,
}) : super(key: key);
@override
State<Handle> createState() => _HandleState();
}
class _HandleState extends State<Handle> {
initState() {
super.initState();
}
String handle = '@';
bool isValid = false;
Future<bool> userExists() async {
bool exist = (await userCollection.where("handle", isEqualTo: handle).get())
.docs
.length >
0;
if (!exist) {
setState(() => isValid = true);
}
}
@override
Widget build(BuildContext context) {
final controller = TextEditingController();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomTextHeader(
tabController: widget.tabController,
text: 'What do you want your handle to be?',
),
SizedBox(height: 10),
CustomTextField(
hint: handle,
initialValue: '@',
decoration: InputDecoration(
errorText: isValid ? null : "Handle already taken",
),
onChanged: (val) {
setState(() => handle = val);
userExists();
},
),
// CustomCheckbox(
],
),
],
),
Column(
children: [
StepProgressIndicator(
totalSteps: 4,
currentStep: 1,
selectedColor: Theme.of(context).primaryColor,
unselectedColor: Theme.of(context).scaffoldBackgroundColor,
),
SizedBox(height: 10),
CustomOnboardingButton(
tabController: widget.tabController,
text: 'NEXT STEP',
id: widget.user.id,
),
],
),
],
),
);
}
}