It seems like you're asking how to display a loader while processing the initial values for the TextFormField widgets inside your FormWidget based on conditions. To achieve this, you can utilize the FutureBuilder widget to show a loader until your asynchronous operations complete. Here’s how you can modify your code:
Add a FutureBuilder: Wrap the part of your code that depends on asynchronous initializations with a FutureBuilder.
Display Loader: Display a loader (e.g., CircularProgressIndicator) while waiting for the async operations to complete.
Here’s an updated version of your _FormWidgetState with these changes:
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:provider/provider.dart';
import 'package:flutter_application_1/view_modal/form_view_model.dart';
import '../../view_modal/influencer_view_model.dart';
class FormWidget extends StatefulWidget {
final String title;
final List<String> fieldLabels;
final String? selectedCurrency;
final List<String>? socialSite;
FormWidget({
required this.title,
required this.fieldLabels,
this.selectedCurrency,
this.socialSite,
});
@override
_FormWidgetState createState() => _FormWidgetState();
}
class _FormWidgetState extends State<FormWidget> {
final _formKey = GlobalKey<FormState>();
final Map<String, String> _formData = {};
String? _selectedCurrency;
bool _isLoggedIn = false;
String? _email;
@override
void initState() {
super.initState();
_selectedCurrency = widget.selectedCurrency;
}
Future<Map<String, String?>> _getCredentials() async {
final secureStorage = FlutterSecureStorage();
String? email = await secureStorage.read(key: 'email');
String? password = await secureStorage.read(key: 'password');
return {'email': email, 'password': password};
}
String extractSocialSite(String label) {
final RegExp regex = RegExp(r'Enter your (.*?) url');
final match = regex.firstMatch(label);
return match?.group(1) ?? '';
}
@override
Widget build(BuildContext context) {
final viewModel = Provider.of<FormViewModel>(context);
final influencerViewModel = Provider.of<InfluencerViewModel>(context);
return FutureBuilder(
future: _getCredentials(),
builder: (context, AsyncSnapshot<Map<String, String?>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else {
Map<String, String?> credentials = snapshot.data ?? {};
String? email = credentials['email'];
String? password = credentials['password'];
if (email != null && password != null && !_isLoggedIn) {
_isLoggedIn = true;
_email = email;
// Fetch data based on email
Provider.of<InfluencerViewModel>(context, listen: false)
.fetchInfluencersData(email);
}
return Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
if (widget.title == 'Set Price')
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column(
children: [
Text('Select Currency'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Radio buttons code here
],
),
],
),
),
for (int i = 0; i < widget.fieldLabels.length; i++)
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Consumer<InfluencerViewModel>(
builder: (context, influencerViewModel, child) {
String fieldKey =
extractSocialSite(widget.fieldLabels[i]);
String? initialValue;
if (widget.title == 'Set Price') {
initialValue =
influencerViewModel.socialPrices?[fieldKey]
?.toString();
} else if (widget.title == 'Add social site') {
initialValue =
influencerViewModel.socialurls?[fieldKey]
?.toString();
}
return TextFormField(
initialValue: initialValue ?? '',
decoration: InputDecoration(
labelText: widget.fieldLabels[i],
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
filled: true,
fillColor: Colors.grey[200],
),
onSaved: (value) {
_formData[widget.fieldLabels[i]] = value ?? '';
},
);
},
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
viewModel.submitForm(_formData, _selectedCurrency);
}
},
child: Text('Save'),
),
],
),
),
),
);
}
},
);
}
}
Explanation:
FutureBuilder: Wraps the widget tree that depends on _getCredentials(). It handles different states (waiting, error, data) and displays appropriate UI (loader, error message, or form content).
Initialization Logic: Moved the logic related to checking credentials and fetching data inside the FutureBuilder. This ensures that the form initializes correctly based on async operations.
TextFormField: The initialValue for each TextFormField is set based on conditions (Set Price or Add social site). This ensures that the form fields are populated correctly once data is available.
By implementing these changes, your form widget will display a loader until the initial values are processed, providing a smoother user experience. Adjust the radio buttons and any other UI elements as per your specific requirements within the form.
Top comments (0)