Flutter failed to post data to create user with API - flutter

I try to create user using api but it throws an exception when executed.
So, here is my json response as below.
{
"success": 1,
"user": {
"user_id": "612f02fc4ae19",
"name": "Test User3",
"mobile": "8347406873",
"email": "dhaval#gmail.com",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344",
"location": "Vyara",
"created_at": "2021-09-01"
},
"msg": "Your account has been created successfully."
}
As response i created model class as below in signup_model.dart file.
import 'dart:convert';
SignupModel signupModelFromJson(String str) =>
SignupModel.fromJson(json.decode(str));
String signupModelToJson(SignupModel data) => json.encode(data.toJson());
class SignupModel {
SignupModel({
this.success,
this.user,
this.msg,
});
int? success;
UserRegistration? user;
String? msg;
factory SignupModel.fromJson(Map<String, dynamic> json) => SignupModel(
success: json["success"],
user: UserRegistration.fromJson(json["user"]),
msg: json["msg"],
);
Map<String, dynamic> toJson() => {
"success": success,
"user": user?.toJson(),
"msg": msg,
};
}
class UserRegistration {
UserRegistration({
this.userId,
this.name,
this.mobile,
this.email,
this.standardId,
this.mediumId,
this.location,
this.createdAt,
});
String? userId;
String? name;
String? mobile;
String? email;
String? standardId;
String? mediumId;
String? location;
DateTime? createdAt;
factory UserRegistration.fromJson(Map<String, dynamic> json) =>
UserRegistration(
userId: json["user_id"],
name: json["name"],
mobile: json["mobile"],
email: json["email"],
standardId: json["standard_id"],
mediumId: json["medium_id"],
location: json["location"],
createdAt: DateTime.parse(json["created_at"]),
);
Map<String, dynamic> toJson() => {
"user_id": userId,
"name": name,
"mobile": mobile,
"email": email,
"standard_id": standardId,
"medium_id": mediumId,
"location": location,
"created_at":
"${createdAt?.year.toString().padLeft(4, '0')}-${createdAt?.month.toString().padLeft(2, '0')}-${createdAt?.day.toString().padLeft(2, '0')}",
};
}
Function which i created as below in api_manager.dart file.
Future<UserRegistration> createUser(
String name,
String email,
String mobile,
String standardId,
String mediumId,
) async {
final registrationUrl = "$baseUrl/user/register";
final response = await http.post(
Uri.parse(registrationUrl),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'name': name,
'email': email,
'mobile': mobile,
'standard_id': standardId,
'medium_id': mediumId,
}),
);
if (response.statusCode == 200) {
print(response.body);
return UserRegistration.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to create User.');
}
}
And My signup screen Code as below in signup_screen.dart file.
class _SignUp1State extends State<SignUp1> {
final baseUrl = SankalpApi().baseUrl;
bool value = false;
var _standards = <Standard>[];
var _mediums = <Medium>[];
Standard? selectedStandard;
Medium? selectedMedium;
var standardId;
var mediumId;
final TextEditingController _nameController = TextEditingController();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _mobileController = TextEditingController();
Future<UserRegistration>? userRegistration;
GlobalKey<FormState> _globalFormKey = GlobalKey<FormState>();
bool isApiCallProcess = false;
#override
void initState() {
super.initState();
ApiManager().getStandards().then((standards) {
setState(() {
_standards = standards;
});
});
}
void onMediumChange(standard) {
setState(() {
selectedStandard = standard;
_mediums = [];
});
String mediumUrl =
"$baseUrl/medium/get_by_course_id?standard_id=${selectedStandard?.standardId}";
ApiManager().getMediums(mediumUrl).then((List<Medium> value) => {
setState(() {
_mediums = value;
})
});
}
#override
Widget build(BuildContext context) {
final Shader linearGradient = LinearGradient(
colors: <Color>[
Color(0xff8921aa),
Color(0xffDA44bb),
],
).createShader(new Rect.fromLTWH(0.0, 0.0, 200.0, 70.0));
return SingleChildScrollView(
child: Form(
key: _globalFormKey,
child: Container(
padding: EdgeInsets.all(12),
child: Column(
children: [
SizedBox(height: 30),
Text(
'Learn from wide range of videos and tutorials',
textAlign: TextAlign.center,
style: GoogleFonts.openSans(
fontSize: 15,
color: Colors.grey[600],
),
),
TextFormField(
decoration: InputDecoration(labelText: "Full Name"),
controller: _nameController,
validator: (value) {
if (value!.isEmpty) {
return "Name is required.";
}
return null;
},
onSaved: (value) {
//this.userRegistration.name = value.toString().trim();
},
),
SizedBox(height: 10),
TextFormField(
decoration: InputDecoration(labelText: "Email"),
controller: _emailController,
validator: (value) {
if (value!.isEmpty) {
return 'Email is required.';
}
if (!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]")
.hasMatch(value)) {
return 'Enter valid Email';
}
return null;
},
onSaved: (value) {
//this.userRegistration.email = value.toString().trim();
},
),
SizedBox(height: 10),
TextFormField(
decoration: InputDecoration(labelText: "Mobile Number"),
controller: _mobileController,
validator: (value) {
String pattern = r'(^[0-9]*$)';
RegExp regExp = new RegExp(pattern);
if (value!.length == 0) {
return "Mobile is required";
} else if (value.length != 10) {
return "Mobile number must 10 digits";
} else if (!regExp.hasMatch(value)) {
return "Mobile Number must be digits";
}
return null;
},
onSaved: (value) {
//this.userRegistration.mobile = value.toString().trim();
},
),
SizedBox(height: 20),
DropdownButtonFormField<Standard>(
validator: (value) {
if (value == null) {
return "Select Standard";
}
},
isExpanded: true,
hint: Text('Select Standard'),
value: selectedStandard,
items: _standards.map((Standard standard) {
return DropdownMenuItem<Standard>(
value: standard,
child: Text(standard.standardName),
);
}).toList(),
onSaved: (value) {
selectedStandard = value;
//this.userRegistration.standardId = value!.standardId;
},
onChanged: (val) {
setState(() {
selectedStandard = val;
standardId = val?.standardId;
// print("StandardId : ${val?.standardId}");
// print("StandardId : ${val?.standardName}");
onMediumChange(val);
});
},
),
SizedBox(height: 20),
DropdownButtonFormField<Medium>(
validator: (value) {
if (value == null) {
return "Select Medium";
}
},
isExpanded: true,
hint: Text('Select Medium'),
value: selectedMedium,
items: _mediums.map((Medium medium) {
return DropdownMenuItem<Medium>(
value: medium,
child: Text(medium.mediumName),
);
}).toList(),
onSaved: (value) {
selectedMedium = value;
//this.userRegistration.mediumId = value!.mediumId;
},
onChanged: (val) {
setState(() {
selectedMedium = val;
mediumId = val?.mediumId;
// print("Medium id : ${val?.mediumId}");
// print("Medium id : ${val?.mediumName}");
});
}),
SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () {
if (validateAndSave()) {
setState(() {
this.isApiCallProcess = true;
print(_nameController.text);
print(_emailController.text);
print(_mobileController.text);
print(standardId);
print(mediumId);
userRegistration = ApiManager().createUser(
_nameController.text,
_emailController.text,
_mobileController.text,
standardId,
mediumId,
);
});
}
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25))),
child: Ink(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
const Color(0xff8921aa),
const Color(0xffDA44bb),
],
),
borderRadius: BorderRadius.circular(25)),
child: Container(
width: 100,
height: 50,
alignment: Alignment.center,
child: Text(
'SIGNUP',
style: TextStyle(
fontSize: 15,
),
),
),
),
),
],
),
SizedBox(
height: 60,
),
Text('Already have an account?'),
TextButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Login2()));
},
child: Text(
'Login',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
foreground: new Paint()..shader = linearGradient,
),
),
)
],
),
),
),
);
}
bool validateAndSave() {
final form = _globalFormKey.currentState;
if (form!.validate()) {
form.save();
return true;
}
return false;
}
}
So, when i try to sign up it thorows an Exception as below.
So what is the problem in given code.?

Related

Image uploads in Firebase but not the data fetched from TextFormFields and dropdownbutton

Flutter beginner here. Working on a flutter project where I can submit a form where I can upload it's content in firebase. I took the data from TextFormField and DropDownButton and the images from ImagePicker. I can upload the image file perfectly to the firebase but the data are not uploading. Here is the code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as path;
class AddDoctor extends StatefulWidget {
#override
State<AddDoctor> createState() => AddDoctorState();
}
class AddDoctorState extends State<AddDoctor> {
late String name;
late int age;
late String description;
String specialistValue = 'Select Specialist';
String hospitalValue = 'Select Hospital';
List<String> imageUrlList = [];
final controllerName = TextEditingController();
final controllerAge = TextEditingController();
final controllerDesciption = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final FirebaseStorage _firebaseStorage = FirebaseStorage.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final ImagePicker _picker = ImagePicker();
XFile? image;
void pickDoctorImage() async {
try {
final pickedImage = await _picker.pickImage(source: ImageSource.gallery);
setState(() {
image = pickedImage!;
});
} catch (e) {}
}
Widget displayImage() {
return Image.file(File(image!.path));
}
Future<void> uploadImage() async {
Reference ref =
_firebaseStorage.ref('products/${path.basename(image!.path)}');
await ref.putFile(File(image!.path)).whenComplete(() async {
await ref.getDownloadURL().then((value) {
imageUrlList.add(value);
});
});
}
void uploadInfo() async {
CollectionReference infoRef = _firestore.collection('DoctorList');
await infoRef.doc().set({
'name': name,
'age': age,
'description': description,
'specialist': specialistValue,
'hospital': hospitalValue,
'doctorImage': imageUrlList,
}).whenComplete(() {
Navigator.pop(context);
});
}
void uploadDoctorInfo() async {
await uploadImage().whenComplete(() => uploadInfo);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFD9E4EE),
appBar: AppBar(
title: const Text('Add Doctor'),
actions: [
IconButton(
icon: const Icon(Icons.menu),
onPressed: () {},
),
],
),
body: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
TextFormField(
keyboardType: TextInputType.name,
validator: (value) {
if (value!.isEmpty) {
return 'Please Name must not be empty';
} else {
return null;
}
},
controller: controllerName,
decoration: const InputDecoration(
label: Text('Name'),
),
onSaved: (value) {
name = value!;
},
),
const SizedBox(height: 10),
TextFormField(
keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) {
return 'Please Age must not be empty';
} else {
return null;
}
},
controller: controllerAge,
decoration: const InputDecoration(
label: Text('Age'),
),
onSaved: (value) {
age = int.parse(value!);
},
),
const SizedBox(height: 10),
DropdownButton(
borderRadius: BorderRadius.circular(30),
value: specialistValue,
items: specialistList.map<DropdownMenuItem<String>>((e) {
return DropdownMenuItem(
value: e,
child: Text(e),
);
}).toList(),
onChanged: (String? value) {
setState(() {
specialistValue = value!;
});
},
),
DropdownButton(
borderRadius: BorderRadius.circular(30),
value: hospitalValue,
items: hospitalList.map<DropdownMenuItem<String>>((e) {
return DropdownMenuItem(
value: e,
child: Text(e),
);
}).toList(),
onChanged: (String? value) {
setState(() {
hospitalValue = value!;
});
},
),
const SizedBox(height: 10),
TextFormField(
keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) {
return 'Please Description must not be empty';
} else {
return null;
}
},
maxLength: 100,
maxLines: 3,
controller: controllerDesciption,
decoration: const InputDecoration(
label: Text('Description'),
),
onChanged: (value) {
description = value;
},
),
const SizedBox(height: 10),
// CircleAvatar(
// radius: 50,
// backgroundImage: image != null ? FileImage(image) : null,
// ),
InkWell(
onTap: () {
setState(() {
image = null;
});
},
child: Container(
padding: const EdgeInsetsDirectional.only(top: 60),
height: 150,
width: 150,
decoration: const BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: Center(
child: image != null
? displayImage()
: const Text(
'You have not pick any image',
style: TextStyle(fontSize: 11),
textAlign: TextAlign.center,
),
)),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
pickDoctorImage();
},
child: const Text('Upload Image'),
),
const SizedBox(height: 10),
ElevatedButton(
child: const Text('Submit'),
onPressed: () {
uploadDoctorInfo();
},
),
],
),
),
);
}
}
There aren't any error in the file either. I can't figure out where the source of the problem is.
Fixed it. The problem was in
void uploadDoctorInfo() async {
await uploadImage().whenComplete(() => uploadInfo);
}
I changed it to
void uploadDoctorInfo() async {
await uploadImage().whenComplete(uploadInfo);
}
And now it's working fine
You should add for the new entry instead set data in collection. Try using the following code
void uploadInfo() async {
CollectionReference infoRef = _firestore.collection('DoctorList');
await infoRef.add({
'name': name,
'age': age,
'description': description,
'specialist': specialistValue,
'hospital': hospitalValue,
'doctorImage': imageUrlList,
}).whenComplete(() {
Navigator.pop(context);
});
}
Edited
Your are referencing uploadInfo function instead of call that. updateInfo should be called by adding (), so uploadDoctorInfo will be look like.
void uploadDoctorInfo() async {
await uploadImage().whenComplete(() => uploadInfo());
}
or
void uploadDoctorInfo() async {
await uploadImage().whenComplete(uploadInfo);
}

type 'Null' is not a subtype of type 'String' in type case

What could be the possible reasons for this error, please guide.
This is my code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/product.dart';
import '../provider/products.dart';
class EditProductScreen extends StatefulWidget {
static const routeName = '/edite-product-screen';
#override
State<EditProductScreen> createState() => _EditProductScreenState();
}
class _EditProductScreenState extends State<EditProductScreen> {
final priceFocusNode = FocusNode();
final descriptionFocusNode = FocusNode();
final imageURLController = TextEditingController();
// TextEditingController listens to updates in the associated TextField and alert its listeners of any changes
final imageURLFocusNode = FocusNode();
final keyForForm = GlobalKey<FormState>();
var emptyProduct =
Product(id: "", title: "", description: "", price: 0, imageUrl: "");
var isInit = true;
var initValues = {
'title': "",
'description': "",
'price': "",
'imageURL': "",
};
#override
void initState() {
super.initState();
imageURLFocusNode.addListener(updateImageUrl);
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
if (isInit) {
final receivedProductID =
ModalRoute.of(context)?.settings.arguments as String;
if (receivedProductID != null) {
emptyProduct = Provider.of<Products>(context, listen: false)
.selectedProduct(receivedProductID);
initValues = {
'title': emptyProduct.title.toString(),
'description': emptyProduct.description.toString(),
'price': emptyProduct.price.toString(),
// 'imageURL': "",
};
imageURLController.text = emptyProduct.imageUrl as String;
}
}
isInit = false;
}
void updateImageUrl() {
if (!imageURLFocusNode.hasFocus) {
if ((!imageURLController.text.startsWith("http") &&
!imageURLController.text.startsWith("https")) ||
(!imageURLController.text.endsWith("jpg") &&
!imageURLController.text.endsWith("png") &&
!imageURLController.text.endsWith("jpeg")) ||
(imageURLController.text.isEmpty)) {
return;
}
setState(() {});
}
}
void saveTheProductBasedOnInformationOfTheForm() {
final validStatus = keyForForm.currentState?.validate();
if (!validStatus!) {
return;
}
keyForForm.currentState?.save();
if (emptyProduct.id != null) {
Provider.of<Products>(context, listen: false)
.updateProduct(emptyProduct.id as String, emptyProduct);
} else {
Provider.of<Products>(context, listen: false).addProduct(emptyProduct);
}
Navigator.of(context).pop();
}
#override
void dispose() {
imageURLFocusNode.removeListener(updateImageUrl);
priceFocusNode.dispose();
descriptionFocusNode.dispose();
imageURLController.dispose();
imageURLFocusNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Products"),
actions: [
IconButton(
onPressed: saveTheProductBasedOnInformationOfTheForm,
icon: Icon(Icons.save))
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: keyForForm,
child: ListView(
children: [
TextFormField(
initialValue: initValues['title'],
validator: (value) {
if (value!.isEmpty) {
return "Please enter a valid value";
} else {
return null;
}
},
decoration: InputDecoration(labelText: "Title"),
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) => {
FocusScope.of(context).requestFocus(priceFocusNode),
},
onSaved: (value) {
emptyProduct = Product(
id: emptyProduct.id,
title: value,
description: emptyProduct.description,
price: emptyProduct.price,
imageUrl: emptyProduct.imageUrl,
isFavorite: emptyProduct.isFavorite);
},
),
TextFormField(
initialValue: initValues['price'],
onSaved: (value) {
emptyProduct = Product(
id: emptyProduct.id,
title: emptyProduct.title,
description: emptyProduct.description,
price: double.parse(value as String),
imageUrl: emptyProduct.imageUrl,
isFavorite: emptyProduct.isFavorite);
},
decoration: InputDecoration(labelText: "Price"),
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
focusNode: priceFocusNode,
onFieldSubmitted: (_) =>
FocusScope.of(context).requestFocus(descriptionFocusNode),
validator: (value) {
if (value!.isEmpty) {
return "Please enter a valid price";
}
if (double.tryParse(value) == null) {
return "Please enter a valid number";
}
if (double.parse(value) <= 0) {
return "Please enter a value greater than 0";
} else {
return null;
}
},
),
TextFormField(
initialValue: initValues['description'],
onSaved: (value) {
emptyProduct = Product(
id: emptyProduct.id,
title: emptyProduct.title,
description: value,
price: emptyProduct.price,
imageUrl: emptyProduct.imageUrl,
isFavorite: emptyProduct.isFavorite);
},
decoration: InputDecoration(labelText: "Description"),
keyboardType: TextInputType.multiline,
maxLines: 3,
validator: (value) {
if (value!.isEmpty) {
return "Please enter a valid description";
}
if (value.length < 10) {
return "Please enter more description";
} else {
return null;
}
},
),
Row(crossAxisAlignment: CrossAxisAlignment.end, children: [
Container(
width: 100,
height: 100,
margin: EdgeInsets.only(top: 10, right: 10),
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.grey)),
child: imageURLController.text.isEmpty
? Text("Please enter URL")
: Image.network(imageURLController.text),
),
Expanded(
child: TextFormField(
initialValue: initValues['imageURL'],
validator: (value) {
if (value!.isEmpty) {
return "Please enter valid Image URL";
}
if ((!value.startsWith("http") &&
!value.startsWith("https")) ||
(!value.endsWith("jpg") &&
!value.endsWith("png") &&
!value.endsWith("jpeg"))) {
return "Please enter a valid URL!";
}
},
onSaved: (value) {
emptyProduct = Product(
id: emptyProduct.id,
title: emptyProduct.title,
description: emptyProduct.description,
price: emptyProduct.price,
imageUrl: value,
isFavorite: emptyProduct.isFavorite);
},
decoration: InputDecoration(labelText: "Image URL"),
keyboardType: TextInputType.url,
textInputAction: TextInputAction.done,
controller: imageURLController,
maxLines: 3,
focusNode: imageURLFocusNode,
onFieldSubmitted: (_) {
saveTheProductBasedOnInformationOfTheForm();
},
),
),
])
],
)),
),
);
}
}
The screen opens without error when (receivedProductID != null), but shows the following error when (receivedProductID == null);
see errror image
And when I try going back from the screen, I see this error
see error image
What could be the possible reasons for this error, please guide.
The reason for the first error is this type cast:
final receivedProductID = ModalRoute.of(context)?.settings.arguments as String;
You cast a nullable value to String. It should be String? instead because it can be null.
final receivedProductID =
ModalRoute.of(context)?.settings.arguments as String?;

type null is not a subtype of string in modal route

import 'package:ecommerce_shop/providers/product.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:ecommerce_shop/providers/products.dart';
class EditProductScreen extends StatefulWidget {
static const routeName = 'edit-product';
const EditProductScreen({Key? key}) : super(key: key);
#override
_EditProductScreenState createState() => _EditProductScreenState();
}
class _EditProductScreenState extends State<EditProductScreen> {
final _priceFocusNode = FocusNode();
final _descriptionFocusNode = FocusNode();
final _imageUrlController = TextEditingController();
final _imageUrlFocusNode = FocusNode();
final _form = GlobalKey<FormState>();
var _edittedProduct = Product(
id: '',
title: '',
description: '',
imageUrl: '',
price: 0,
);
var _initValues = {
'title': '',
'description': '',
'price': '',
'imageUrl': '',
'id': '',
};
var _isInit = true;
#override
void initState() {
_imageUrlFocusNode.addListener(_updateImageUrl);
super.initState();
}
#override
void didChangeDependencies() {
if (_isInit) {
final productId = ModalRoute.of(context)?.settings.arguments as String;
if (productId != null) {
_edittedProduct =
Provider.of<Products>(context, listen: false).findById(productId);
_initValues = {
'id': _edittedProduct.id,
'title': _edittedProduct.title,
'description': _edittedProduct.description,
'price': _edittedProduct.price.toString(),
// 'imageUrl': _editedProduct.imageUrl,
'imageUrl': '',
};
_imageUrlController.text = _edittedProduct.imageUrl;
}
}
// if (_isInit) {
// // var productId = ModalRoute.of(context)!.settings.arguments ?? "";
// // // var productId =
// // // ModalRoute.of(context)!.settings.arguments as String ?? " ";
// // // productId ??= " ";
// // // final productId = ModalRoute.of(context)!.settings.arguments as String;
// // // print('$productId **********************************************');
// // _edittedProduct = Provider.of<Products>(
// // context,
// // listen: false,
// // ).findById(productId as String);
// }
_isInit = false;
super.didChangeDependencies();
}
void _updateImageUrl() {
if (_imageUrlController.text.isEmpty ||
!_imageUrlController.text.startsWith('http') ||
!_imageUrlController.text.startsWith('https')) {
return;
}
if (!_imageUrlFocusNode.hasFocus) {
setState(() {});
}
}
#override
void dispose() {
_imageUrlFocusNode.removeListener(_updateImageUrl);
_priceFocusNode.dispose();
_descriptionFocusNode.dispose();
super.dispose();
_imageUrlController.dispose();
_imageUrlFocusNode.dispose();
}
void _saveForm() {
final isValid = _form.currentState!.validate();
if (!isValid) {
return;
}
_form.currentState!.save();
Provider.of<Products>(context, listen: false).addProduct(_edittedProduct);
// _form.currentState!.save();
// if (_edittedProduct.id != '') {
// Provider.of<Products>(context, listen: false)
// .updateProduct(_edittedProduct.id!, _edittedProduct);
// } else {
// }
Navigator.of(context).pop();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Edit Product'),
actions: [
IconButton(
onPressed: _saveForm,
icon: const Icon(Icons.save),
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _form,
child: ListView(
children: [
TextFormField(
initialValue: _initValues['title'],
decoration: const InputDecoration(
labelText: 'Title',
),
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_priceFocusNode);
},
validator: (value) {
if (value!.isEmpty) {
return 'please provide a value';
}
return null;
},
onSaved: (value) {
_edittedProduct = Product(
id: _edittedProduct.id,
isFavourite: _edittedProduct.isFavourite,
title: value!,
description: _edittedProduct.description,
imageUrl: _edittedProduct.imageUrl,
price: _edittedProduct.price);
},
),
TextFormField(
initialValue: _initValues['price'],
decoration: const InputDecoration(
labelText: 'Price',
),
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
focusNode: _priceFocusNode,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_descriptionFocusNode);
},
validator: (value) {
if (value!.isEmpty) {
return 'please enter a price';
}
if (double.tryParse(value) == null) {
return 'Please enter a valid number';
}
if (double.parse(value) <= 0) {
return 'please enter a number greater than 0';
}
return null;
},
onSaved: (value) {
_edittedProduct = Product(
id: _edittedProduct.id,
isFavourite: _edittedProduct.isFavourite,
title: _edittedProduct.title,
description: _edittedProduct.description,
imageUrl: _edittedProduct.imageUrl,
price: double.parse(value!),
);
},
),
TextFormField(
initialValue: _initValues['description'],
decoration: const InputDecoration(
labelText: 'Description',
),
maxLines: 3,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.multiline,
focusNode: _descriptionFocusNode,
validator: (value) {
if (value!.isEmpty) {
return 'please enter a description';
}
if (value.length < 10) {
return 'should be atleast 10 characters long';
}
return null;
},
onSaved: (value) {
_edittedProduct = Product(
id: _edittedProduct.id,
isFavourite: _edittedProduct.isFavourite,
title: _edittedProduct.title,
description: value!,
imageUrl: _edittedProduct.imageUrl,
price: _edittedProduct.price);
},
),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
width: 100,
height: 100,
margin: const EdgeInsets.only(
top: 8,
right: 10,
),
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.grey),
),
child: Container(
child: _imageUrlController.text.isEmpty
? const Text('Enter a Url ')
: FittedBox(
child: Image.network(
_imageUrlController.text,
fit: BoxFit.cover,
),
),
),
),
Expanded(
child: TextFormField(
// initialValue: _initValues['imageUrl'],
decoration: const InputDecoration(labelText: 'Image Url'),
keyboardType: TextInputType.url,
textInputAction: TextInputAction.done,
controller: _imageUrlController,
focusNode: _imageUrlFocusNode,
onFieldSubmitted: (_) {
_saveForm();
},
validator: (value) {
return null;
},
onSaved: (value) {
_edittedProduct = Product(
id: _edittedProduct.id,
isFavourite: _edittedProduct.isFavourite,
title: _edittedProduct.title,
description: _edittedProduct.description,
imageUrl: value!,
price: _edittedProduct.price);
},
),
),
],
),
],
),
),
),
);
}
}
This is the code and I am getting the error as null is not a subtype of string But I couldn't get how to resolve it, if you want my complete project files for checking
it is on https://github.com/SaivigneshAdepu20/ecommerce_shop.Actually I have shared the arguments in provider as id in product item screen which is available in my Github account.
What exactly contents do you expect? If it i s List or similar, try:
final List<String> files = ModalRoute
.of(context)
.settings
.arguments as List<String>;
Also it may be that you try calling .of(context) too soon. Try closing it in
Future.delayed(Duration.zero,(){
//Here
});
i'm following the same tutorial and this is code below fix it
#override
void didChangeDependencies() {
if (_isInit == true) {
final String productId = ModalRoute.of(context)?.settings.arguments == null ? '':ModalRoute.of(context)!.settings.arguments as String;
if (productId.isEmpty != true) {
final product =
Provider.of<Products>(context, listen: false).findById(productId!);
_editProduct = product;
_initValues = {
'title': _editProduct.title,
'price': _editProduct.price.toString(),
'description': _editProduct.description,
'imageUrl': _editProduct.imageUrl
};
_imageUrlController.text= _editProduct.imageUrl;
}
}
_isInit = false;
// TODO: implement didChangeDependencies
super.didChangeDependencies();
}

Is it possible to POST Data using localhost woocommerce rest api in flutter

Is it possible to POST data from flutter app to woocommerce localhost using woocommerce localhost server rest api.
i have GET & POST data with private domain but i want to POST & GET data with localhost woocommerce rest api. i have setup my wordpress and woocommerce on localhost I am trying to make flutter ecommerce app and trying to GET & POST data from woocommerce localhost. but its not working and i dont want to send from private domain rest api, i can get data on postman if i select OAuth 1.0 but if i dont use OAuth 1.0 i cant get data.
Config.dart
class Config {
static String key =
'ck_00000000000000000000000000';
static String sceret =
'cs_00000000000000000000000000';
static String url = 'http://10.0.2.2:80/wordpress_new/wp-json/wc/v3/';
static String customerURL = 'customers';
}
customer.dart
class CustomerModel {
String email;
String firstName;
String lastName;
String password;
CustomerModel({
this.email,
this.firstName,
this.lastName,
this.password,
});
Map<String, dynamic> toJson() {
Map<String, dynamic> map = {};
map.addAll({
'email': email,
'first_name': firstName,
'last_name': lastName,
'password': password,
'username': email,
});
return map;
}
}
apiservice.dart
class APIService {
Future<bool> createCustomer(CustomerModel model) async {
var authToken = base64.encode(
utf8.encode(Config.key + ':' + Config.sceret),
);
bool ret = false;
try {
var response = await Dio().post(
Config.url +
Config.customerURL,
data: model.toJson(),
options: new Options(headers: {
HttpHeaders.authorizationHeader: 'Basic $authToken',
HttpHeaders.contentTypeHeader: 'application/json',
}));
if (response.statusCode == 201) {
ret = true;
}
} on DioError catch (e) {
if (e.response.statusCode == 404) {
print(e.response.statusCode);
ret = false;
} else {
print(e.message);
print(e.request);
ret = false;
}
}
return ret;
}
Future<LoginResponseModel> loginCustomer(
String username,
String password,
) async {
LoginResponseModel model;
try {
var response = await Dio().post(Config.tokenURL,
data: {
'username': username,
'password': password,
},
options: new Options(headers: {
HttpHeaders.contentTypeHeader: 'application/x-www-form-urlencoded',
}));
if (response.statusCode == 200) {
model = LoginResponseModel.fromJson(response.data);
}
} on DioError catch (e) {
print(e.message);
}
return model;
}
}
signuppage.dart
class SignupPage extends StatefulWidget {
#override
_SignupPageState createState() => _SignupPageState();
}
class _SignupPageState extends State<SignupPage> {
APIService apiService;
CustomerModel model;
GlobalKey<FormState> globalKey = GlobalKey<FormState>();
bool hidePassword = true;
bool isApiCallProcess = false;
#override
void initState() {
apiService = new APIService();
model = new CustomerModel();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
automaticallyImplyLeading: true,
title: Text('Sign Up'),
),
body: ProgressHUD(
child: Form(
key: globalKey,
child: _formUI(),
),
inAsyncCall: isApiCallProcess,
opacity: 0.3),
);
}
Widget _formUI() {
return SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(10.00),
child: Container(
child: Align(
alignment: Alignment.topLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
FormHelper.fieldLabel('First Name'),
FormHelper.textInput(
context,
model.firstName,
(value) => {
this.model.firstName = value,
},
onValidate: (value) {
if (value.toString().isEmpty) {
return 'Please enter First Name.';
}
return null;
},
),
FormHelper.fieldLabel('Last Name'),
FormHelper.textInput(
context,
model.lastName,
(value) => {
this.model.lastName = value,
},
onValidate: (value) {
return null;
},
),
FormHelper.fieldLabel('Email Id'),
FormHelper.textInput(
context,
model.email,
(value) => {
this.model.email = value,
},
onValidate: (value) {
if (value.toString().isEmpty) {
return 'Please enter Email id.';
}
if (value.isNotEmpty && !value.toString().isValidEmail()) {
return 'Please enter valid email id';
}
},
),
FormHelper.fieldLabel('Password'),
FormHelper.textInput(
context,
model.password,
(value) => {
this.model.password = value,
},
onValidate: (value) {
if (value.toString().isEmpty) {
return 'Please enter Password.';
}
return null;
},
obscureText: hidePassword,
suffixIcon: IconButton(
onPressed: () {
setState(() {
hidePassword = !hidePassword;
});
},
color: Theme.of(context).accentColor.withOpacity(0.4),
icon: Icon(
hidePassword ? Icons.visibility_off : Icons.visibility,
),
),
),
SizedBox(
height: 20,
),
Center(
child: FormHelper.saveButton(
'Register',
() {
if (validateAndSave()) {
print(model.toJson());
setState(() {
isApiCallProcess = true;
});
apiService.createCustomer(model).then(
(ret) {
setState(() {
isApiCallProcess = false;
});
if (ret) {
FormHelper.showMessage(
context,
'WooCommerce App',
'Registration Successfull',
'Ok',
() {
Navigator.of(context).pop();
},
);
} else {
FormHelper.showMessage(
context,
'WooCommerce App',
'Email Id already registered.',
'Ok',
() {
Navigator.of(context).pop();
},
);
}
},
);
}
},
),
)
],
),
),
),
),
);
}
bool validateAndSave() {
final form = globalKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
}
form_helper.dart
class FormHelper {
static Widget textInput(
BuildContext context,
Object initialValue,
Function onChanged, {
bool isTextArea = false,
bool isNumberInput = false,
obscureText: false,
Function onValidate,
Widget prefixIcon,
Widget suffixIcon,
}) {
return TextFormField(
initialValue: initialValue != null ? initialValue.toString() : "",
decoration: fieldDecoration(
context,
"",
"",
suffixIcon: suffixIcon,
),
obscureText: obscureText,
maxLines: !isTextArea ? 1 : 3,
keyboardType: isNumberInput ? TextInputType.number : TextInputType.text,
onChanged: (String value) {
return onChanged(value);
},
validator: (value) {
return onValidate(value);
},
);
}
static InputDecoration fieldDecoration(
BuildContext context,
String hintText,
String helperText, {
Widget prefixIcon,
Widget suffixIcon,
}) {
return InputDecoration(
contentPadding: EdgeInsets.all(6),
hintText: hintText,
helperText: helperText,
prefixIcon: prefixIcon,
suffixIcon: suffixIcon,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
width: 1,
),
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
width: 1,
),
),
);
}
static Widget fieldLabel(String labelName) {
return new Padding(
padding: EdgeInsets.fromLTRB(0, 5, 0, 10),
child: Text(
labelName,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
),
);
}
static Widget saveButton(String buttonText, Function onTap,
{String color, String textColor, bool fullWidth}) {
return Container(
height: 50.0,
width: 150,
child: GestureDetector(
onTap: () {
onTap();
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.redAccent,
style: BorderStyle.solid,
width: 1.0,
),
color: Colors.redAccent,
borderRadius: BorderRadius.circular(30.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Text(
buttonText,
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
letterSpacing: 1,
),
),
),
],
),
),
),
);
}
static void showMessage(
BuildContext context,
String title,
String message,
String buttonText,
Function onPressed,
) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(title),
content: new Text(message),
actions: [
new FlatButton(
onPressed: () {
return onPressed();
},
child: new Text(buttonText),
)
],
);
},
);
}
}
progressHUD.dart
class ProgressHUD extends StatelessWidget {
final Widget child;
final bool inAsyncCall;
final double opacity;
final Color color;
final Animation<Color> valueColor;
ProgressHUD({
Key key,
#required this.child,
#required this.inAsyncCall,
this.opacity = 0.3,
this.color = Colors.grey,
this.valueColor,
}) : super(key: key);
#override
Widget build(BuildContext context) {
List<Widget> widgetList = new List<Widget>();
widgetList.add(child);
if (inAsyncCall) {
final modal = new Stack(
children: [
new Opacity(
opacity: opacity,
child: ModalBarrier(dismissible: false, color: color),
),
new Center(child: new CircularProgressIndicator()),
],
);
widgetList.add(modal);
}
return Stack(
children: widgetList,
);
}
}

How to populating 2nd DropdownMenu based on first item selected flutter

I'm populating states name from JSON and display as a dropdown list after that I show 2nd dropdown list based on first value selected. But I don't now how to populate 2nd dropdown when 1st dropdown value changed. I also want to get location id, name and city when select 2nd dropdown value.
My Json
{
"data": [
{
"state": "TEXAS",
"locations": [
{
"id": 1,
"name": "FITT Sugarland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "HOUSTON SUGARLAND",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:17:55.000Z",
"modifiedAt": "2020-08-18T10:17:55.000Z"
},
{
"id": 2,
"name": "FITT Pearland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "second location",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:18:38.000Z",
"modifiedAt": "2020-08-18T10:18:38.000Z"
}
]
}
]
}
Model Class
class LocationModel {
List<LocationList> data;
LocationModel({this.data});
LocationModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = new List<LocationList>();
json['data'].forEach((v) {
data.add(new LocationList.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
return data;
}
}
class LocationList {
String state;
List<Locations> locations;
LocationList({this.state, this.locations});
LocationList.fromJson(Map<String, dynamic> json) {
state = json['state'];
if (json['locations'] != null) {
locations = new List<Locations>();
json['locations'].forEach((v) {
locations.add(new Locations.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['state'] = this.state;
if (this.locations != null) {
data['locations'] = this.locations.map((v) => v.toJson()).toList();
}
return data;
}
}
class Locations {
int id;
String name;
String city;
String state;
String timezone;
String ownerName;
String ownerPhoneNumber;
String ownerEmail;
String ownerWebsite;
int capacity;
String description;
String createdBy;
String modifiedBy;
String createdAt;
String modifiedAt;
Locations(
{this.id,
this.name,
this.city,
this.state,
this.timezone,
this.ownerName,
this.ownerPhoneNumber,
this.ownerEmail,
this.ownerWebsite,
this.capacity,
this.description,
this.createdBy,
this.modifiedBy,
this.createdAt,
this.modifiedAt});
Locations.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
city = json['city'];
state = json['state'];
timezone = json['timezone'];
ownerName = json['ownerName'];
ownerPhoneNumber = json['ownerPhoneNumber'];
ownerEmail = json['ownerEmail'];
ownerWebsite = json['ownerWebsite'];
capacity = json['capacity'];
description = json['description'];
createdBy = json['createdBy'];
modifiedBy = json['modifiedBy'];
createdAt = json['createdAt'];
modifiedAt = json['modifiedAt'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['city'] = this.city;
data['state'] = this.state;
data['timezone'] = this.timezone;
data['ownerName'] = this.ownerName;
data['ownerPhoneNumber'] = this.ownerPhoneNumber;
data['ownerEmail'] = this.ownerEmail;
data['ownerWebsite'] = this.ownerWebsite;
data['capacity'] = this.capacity;
data['description'] = this.description;
data['createdBy'] = this.createdBy;
data['modifiedBy'] = this.modifiedBy;
data['createdAt'] = this.createdAt;
data['modifiedAt'] = this.modifiedAt;
return data;
}
}
My Code
import 'dart:io';
import 'package:fittheorem/models/location_list.dart';
import 'package:fittheorem/providers/auth_session.dart';
import 'package:fittheorem/providers/user_details.dart';
import 'package:fittheorem/ui/widgets/error_snakbar.dart';
import 'package:fittheorem/utils/app_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class LocationUpdate extends StatefulWidget {
#override
_LocationUpdateState createState() => _LocationUpdateState();
}
class _LocationUpdateState extends State<LocationUpdate> {
LocationModel _locationModel;
bool isLoading = true;
String _selectedState = "TEXAS";
List<String> _statesList = [];
String _selectedLocation = "FITT Sugarland";
List<Locations> _locationsList = List();
#override
void initState() {
// TODO: implement initState
super.initState();
getList();
}
Future<void> getList() async {
try {
_locationModel = await Provider.of<UserDetails>(context, listen: false)
.getLocationList("token");
for (int i = 0; i < _locationModel.data.length; i++) {
_statesList.add(_locationModel.data[i].state);
}
_locationsList = _locationModel.data[0].locations;
_selectedState = _statesList[0];
_selectedLocation = _locationsList[0].name;
if (mounted) {
setState(() {
isLoading = false;
});
}
} on HttpException catch (error) {
CustomWidgets.buildErrorSnackbar(context);
} catch (error) {
CustomWidgets.buildErrorSnackbar(context);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: AppConfig.bgColor,
child: SafeArea(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
height: 40.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.pop(context, true);
},
child: Container(
height: 25.0,
width: 25.0,
child: SvgPicture.asset(AppConfig.backImage,
color: Colors.white, semanticsLabel: 'back')),
),
Text('LOCATION',
style: GoogleFonts.roboto(
textStyle: TextStyle(
fontSize: 18.0, color: Color(0xffFFFFFF)),
)),
SizedBox(
width: 25.0,
),
],
),
),
Expanded(
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(30.0),
child: isLoading
? Center(
child: AppConfig().myLoader(),
)
: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 20.0,
),
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Text('UPDATE YOUR LOCATION',
style: GoogleFonts.roboto(
textStyle: TextStyle(
fontSize: 16.0,
color: Color(0xff000000)),
)),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: new BoxDecoration(
border: new Border.all(
color: Colors.black54, width: 0.0),
borderRadius: new BorderRadius.circular(10.0),
),
child: new DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: new DropdownButton(
value: _selectedState,
hint: Text("State"),
isExpanded: true,
items: _statesList
.map((String item) =>
DropdownMenuItem<String>(
child: Text(item),
value: item))
.toList(),
onChanged: (String newValue) {
if (mounted)
setState(() {
_selectedState = newValue;
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: new BoxDecoration(
border: new Border.all(
color: Colors.black54, width: 0.0),
borderRadius: new BorderRadius.circular(10.0),
),
child: new DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: new DropdownButton(
value: _selectedLocation,
hint: Text("Location"),
isExpanded: true,
items: _locationsList.map((item) {
return new DropdownMenuItem(
child: new Text(item.name),
value: item.name,
);
}).toList(),
onChanged: (newValue) {
if (mounted) print(newValue);
setState(() {
_selectedLocation = newValue;
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
)
],
),
),
)
],
),
),
),
);
}
}
You can copy paste run full code below
Step 1: Change data type of _selectedLocation
Locations _selectedLocation;
Step 2: _selectedState's onChanged
onChanged: (String Value) {
if (mounted)
setState(() {
_selectedState = Value;
int index = _locationModel.data
.indexWhere((element) =>
element.state ==
_selectedState);
_locationsList = _locationModel
.data[index].locations;
_selectedLocation =
_locationsList[0];
});
},
Step 3: _selectedLocation's onChanged
onChanged: (Value) {
if (mounted) print(Value);
setState(() {
_selectedLocation = Value;
print(
"${_selectedLocation.name} ${_selectedLocation.id} ${_selectedLocation.city}");
});
},
working demo
full code
import 'dart:convert';
import 'package:flutter/material.dart';
LocationModel locationModelFromJson(String str) =>
LocationModel.fromJson(json.decode(str));
class LocationModel {
List<LocationList> data;
LocationModel({this.data});
LocationModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = List<LocationList>();
json['data'].forEach((v) {
data.add(LocationList.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
return data;
}
}
class LocationList {
String state;
List<Locations> locations;
LocationList({this.state, this.locations});
LocationList.fromJson(Map<String, dynamic> json) {
state = json['state'];
if (json['locations'] != null) {
locations = List<Locations>();
json['locations'].forEach((v) {
locations.add(Locations.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['state'] = this.state;
if (this.locations != null) {
data['locations'] = this.locations.map((v) => v.toJson()).toList();
}
return data;
}
}
class Locations {
int id;
String name;
String city;
String state;
String timezone;
String ownerName;
String ownerPhoneNumber;
String ownerEmail;
String ownerWebsite;
int capacity;
String description;
String createdBy;
String modifiedBy;
String createdAt;
String modifiedAt;
Locations(
{this.id,
this.name,
this.city,
this.state,
this.timezone,
this.ownerName,
this.ownerPhoneNumber,
this.ownerEmail,
this.ownerWebsite,
this.capacity,
this.description,
this.createdBy,
this.modifiedBy,
this.createdAt,
this.modifiedAt});
Locations.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
city = json['city'];
state = json['state'];
timezone = json['timezone'];
ownerName = json['ownerName'];
ownerPhoneNumber = json['ownerPhoneNumber'];
ownerEmail = json['ownerEmail'];
ownerWebsite = json['ownerWebsite'];
capacity = json['capacity'];
description = json['description'];
createdBy = json['createdBy'];
modifiedBy = json['modifiedBy'];
createdAt = json['createdAt'];
modifiedAt = json['modifiedAt'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['city'] = this.city;
data['state'] = this.state;
data['timezone'] = this.timezone;
data['ownerName'] = this.ownerName;
data['ownerPhoneNumber'] = this.ownerPhoneNumber;
data['ownerEmail'] = this.ownerEmail;
data['ownerWebsite'] = this.ownerWebsite;
data['capacity'] = this.capacity;
data['description'] = this.description;
data['createdBy'] = this.createdBy;
data['modifiedBy'] = this.modifiedBy;
data['createdAt'] = this.createdAt;
data['modifiedAt'] = this.modifiedAt;
return data;
}
}
class LocationUpdate extends StatefulWidget {
#override
_LocationUpdateState createState() => _LocationUpdateState();
}
class _LocationUpdateState extends State<LocationUpdate> {
LocationModel _locationModel;
bool isLoading = true;
String _selectedState = "TEXAS";
List<String> _statesList = [];
Locations _selectedLocation;
List<Locations> _locationsList = List();
#override
void initState() {
// TODO: implement initState
super.initState();
getList();
}
Future<void> getList() async {
try {
/*_locationModel = await Provider.of<UserDetails>(context, listen: false)
.getLocationList("token");*/
String jsonString = '''
{
"data": [
{
"state": "TEXAS",
"locations": [
{
"id": 1,
"name": "FITT Sugarland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "HOUSTON SUGARLAND",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:17:55.000Z",
"modifiedAt": "2020-08-18T10:17:55.000Z"
},
{
"id": 2,
"name": "FITT Pearland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "second location",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:18:38.000Z",
"modifiedAt": "2020-08-18T10:18:38.000Z"
}
]
},
{
"state": "A",
"locations": [
{
"id": 1,
"name": "A1",
"city": "A City 1",
"state": "A",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "HOUSTON SUGARLAND",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:17:55.000Z",
"modifiedAt": "2020-08-18T10:17:55.000Z"
},
{
"id": 2,
"name": "A2",
"city": "A city 2",
"state": "A",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "second location",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:18:38.000Z",
"modifiedAt": "2020-08-18T10:18:38.000Z"
}
]
}
]
}
''';
_locationModel = locationModelFromJson(jsonString);
for (int i = 0; i < _locationModel.data.length; i++) {
_statesList.add(_locationModel.data[i].state);
}
_locationsList = _locationModel.data[0].locations;
_selectedState = _statesList[0];
_selectedLocation = _locationsList[0];
if (mounted) {
setState(() {
isLoading = false;
});
}
//} on HttpException catch (error) {
// CustomWidgets.buildErrorSnackbar(context);
} catch (error) {
//CustomWidgets.buildErrorSnackbar(context);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
//color: AppConfig.bgColor,
child: SafeArea(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
height: 40.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.pop(context, true);
},
child: Container(
height: 25.0,
width: 25.0,
child: Image.network(
'https://picsum.photos/250?image=9',
color: Colors.white)),
),
Text('LOCATION',
style: TextStyle(
fontSize: 18.0,
color: Color(0xffFFFFFF),
)),
SizedBox(
width: 25.0,
),
],
),
),
Expanded(
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(30.0),
child: isLoading
? Center(
child: CircularProgressIndicator(),
)
: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 20.0,
),
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Text('UPDATE YOUR LOCATION',
style: TextStyle(
fontSize: 16.0,
color: Color(0xff000000),
)),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black54, width: 0.0),
borderRadius: BorderRadius.circular(10.0),
),
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
value: _selectedState,
hint: Text("State"),
isExpanded: true,
items: _statesList
.map((String item) =>
DropdownMenuItem<String>(
child: Text(item),
value: item))
.toList(),
onChanged: (String Value) {
if (mounted)
setState(() {
_selectedState = Value;
int index = _locationModel.data
.indexWhere((element) =>
element.state ==
_selectedState);
_locationsList = _locationModel
.data[index].locations;
_selectedLocation =
_locationsList[0];
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black54, width: 0.0),
borderRadius: BorderRadius.circular(10.0),
),
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
value: _selectedLocation,
hint: Text("Location"),
isExpanded: true,
items: _locationsList.map((item) {
return DropdownMenuItem(
child: Text(item.name),
value: item,
);
}).toList(),
onChanged: (Value) {
if (mounted) print(Value);
setState(() {
_selectedLocation = Value;
print(
"${_selectedLocation.name} ${_selectedLocation.id} ${_selectedLocation.city}");
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
)
],
),
),
)
],
),
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: LocationUpdate(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}