Comma separated in AutoCompleteTextField in flutter - flutter

I am using a code which is working well and giving suggestion in dropdown menu by send a HTTP GET request.
import 'package:http/http.dart' as http;
import 'user.dart';
import 'dart:convert';
import 'package:autocomplete_textfield/autocomplete_textfield.dart';
class AutoCompleteDemo extends StatefulWidget {
AutoCompleteDemo() : super();
final String title = "AutoComplete Demo";
#override
_AutoCompleteDemoState createState() => _AutoCompleteDemoState();
}
class _AutoCompleteDemoState extends State<AutoCompleteDemo> {
AutoCompleteTextField searchTextField;
GlobalKey<AutoCompleteTextFieldState<User>> key = new GlobalKey();
static List<User> users = new List<User>();
bool loading = true;
void getUsers() async {
try {
final response =
await http.get("https://jsonplaceholder.typicode.com/users");
if (response.statusCode == 200) {
users = loadUsers(response.body);
print('Users: ${users.length}');
setState(() {
loading = false;
});
} else {
print("Error getting users.");
}
} catch (e) {
print("Error getting users.");
}
}
static List<User> loadUsers(String jsonString) {
final parsed = json.decode(jsonString).cast<Map<String, dynamic>>();
return parsed.map<User>((json) => User.fromJson(json)).toList();
}
#override
void initState() {
getUsers();
super.initState();
}
Widget row(User user) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
user.name,
style: TextStyle(fontSize: 16.0),
),
SizedBox(
width: 10.0,
),
Text(
user.email,
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
loading
? CircularProgressIndicator()
: searchTextField = AutoCompleteTextField<User>(
key: key,
clearOnSubmit: false,
suggestions: users,
style: TextStyle(color: Colors.black, fontSize: 16.0),
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(10.0, 30.0, 10.0, 20.0),
hintText: "Search Name",
hintStyle: TextStyle(color: Colors.black),
),
itemFilter: (item, query) {
return item.name
.toLowerCase()
.startsWith(query.toLowerCase());
},
itemSorter: (a, b) {
return a.name.compareTo(b.name);
},
itemSubmitted: (item) {
setState(() {
searchTextField.textField.controller.text = item.name;
});
},
itemBuilder: (context, item) {
// ui for the autocompelete row
return row(item);
},
),
],
),
);
}
}
Requirement:
I want to take the input something like this so that every selected item is separated and the drop-down list shown after an item selected.The user could be able to add its own new item which isn't from the list.

Related

Composing region changed by the framework. Restarting the input method in Flutter

First time I'm able to send the message and get the response but second time it's not giving me the response as showing error as Composing region changed by the framework. Restarting the input method. Also sometimes not even the single time showing me the response.
It is working on the web perfectly but the issue on the we is it is giving me response once in the first time, twice in second time, thrice in third time.
import 'chatmessage.dart';
import 'threedots.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({super.key});
#override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _controller = TextEditingController();
final List<ChatMessage> _messages = [];
Chat? chat;
bool _isImageSearch = false;
StreamSubscription? _subscription;
bool _isTyping = false;
#override
void initState() {
super.initState();
chat = Chat.instance.builder(
"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",
);
}
#override
void dispose() {
chat!.genImgClose();
_subscription?.cancel();
super.dispose();
}
void _sendMessage() {
if (_controller.text.isEmpty) return;
ChatMessage message = ChatMessage(
text: _controller.text,
sender: "Me",
isImage: false,
);
setState(() {
_messages.insert(0, message);
_isTyping = true;
});
_controller.clear();
if (_isImageSearch) {
final request = GenerateImage(message.text, 1, size: "256x256");
_subscription = chat!
.generateImageStream(request)
.asBroadcastStream()
.listen((response) {
Vx.log(response.data!.last!.url!);
insertNewData(response.data!.last!.url!, isImage: true);
});
} else {
final request = CompleteReq(
prompt: message.text, model: kTranslateModelV3, max_tokens: 200);
_subscription = chat!
.onCompleteStream(request: request)
.asBroadcastStream()
.listen((response) {
Vx.log(response!.choices[0].text);
insertNewData(response.choices[0].text, isImage: false);
});
}
}
void insertNewData(String response, {bool isImage = false}) {
ChatMessage botMessage = ChatMessage(
text: response,
sender: "AI Bot",
isImage: isImage,
);
setState(() {
_isTyping = false;
_messages.insert(0, botMessage);
});
}
Widget _buildTextComposer() {
return Row(
children: [
Expanded(
child: TextField(
controller: _controller,
onSubmitted: (value) => _sendMessage(),
decoration: const InputDecoration.collapsed(
hintText: "Question/Description"),
),
),
ButtonBar(
children: [
IconButton(
icon: const Icon(Icons.send),
onPressed: () {
_isImageSearch = false;
_sendMessage();
},
),
// TextButton(
// onPressed: () {
// _isImageSearch = true;
// _sendMessage();
// },
// child: const Text("Generate Image"))
],
),
],
).px16();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text(
"Welcome To AI Bot",
textAlign: TextAlign.center,
),
backgroundColor: Color.fromARGB(202, 245, 235, 104),
),
body: SafeArea(
child: Column(
children: [
Flexible(
child: ListView.builder(
reverse: true,
padding: Vx.m8,
itemCount: _messages.length,
itemBuilder: (context, index) {
return _messages[index];
},
)),
if (_isTyping) const ThreeDots(),
const Divider(
height: 1.0,
),
Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.lightGreen,
),
child: _buildTextComposer(),
)
],
),
));
}
}

Duplicate GlobalKey detected in tree widget scaffoldState

I was trying to update data (add, edit, delete) from my list using API, when I clicked something to update the list e.g deleting an item it showed a successfully updated. but in the Debug Console, there's an error that says
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in the widget tree. The following GlobalKey
was specified multiple times in the widget tree. This will lead to
parts of the widget tree being truncated unexpectedly, because the
second time a key is seen, the previous instance is moved to the new
location. The key was:
[LabeledGlobalKey #47c37] This was determined by noticing that after the widget with the above global key was moved out
of its previous parent, that previous parent never updated during this
frame, meaning that it either did not update at all or updated before
the widget was moved, in either case implying that it still thinks
that it should have a child with that global key.
And when I tried going back to the Previous screen it just showed Blank Screen
Here's the code
Model
import 'dart:convert';
class Nasabah {
int id;
String nama_debitur;
String alamat;
String no_telp;
String no_ktp;
String no_selular;
Nasabah({
this.id = 0,
this.nama_debitur,
this.alamat,
this.no_telp,
this.no_ktp,
this.no_selular,
});
factory Nasabah.fromJson(Map<String, dynamic> json) => Nasabah(
id: json["id"],
nama_debitur: json["nama_debitur"],
alamat: json["alamat"],
no_telp: json["no_telp"],
no_ktp: json["no_ktp"],
no_selular: json["no_selular"],
);
factory Nasabah.fromMap(Map<String, dynamic> map) => Nasabah(
id: map["id"],
nama_debitur: map["nama_debitur"],
alamat: map["alamat"],
no_telp: map["no_telp"],
no_ktp: map["no_ktp"],
no_selular: map["no_selular"],
);
Map<String, dynamic> toJson() => {
"id": id,
"nama_debitur": nama_debitur,
"alamat": alamat,
"no_telp": no_telp,
"no_ktp": no_ktp,
"no_selular": no_selular,
};
#override
String toString() {
return 'Nasabah{id: $id, nama_debitur: $nama_debitur, alamat: $alamat, no_telp: $no_telp, no_ktp: $no_ktp, no_selular: $no_selular}';
}
}
class NasabahResult {
String status;
List<Nasabah> data = new List<Nasabah>();
NasabahResult({
this.status,
this.data,
});
factory NasabahResult.fromJson(Map<String, dynamic> data) => NasabahResult(
status: data["status"],
data: List<Nasabah>.from(
data["data"].map((item) => Nasabah.fromJson(item))),
);
}
NasabahResult nasabahResultFromJson(String jsonData) {
final data = json.decode(jsonData);
return NasabahResult.fromJson(data);
}
String nasabahToJson(Nasabah nasabah) {
final jsonData = nasabah.toJson();
return json.encode(jsonData);
}
Service
import 'package:flutter_auth/Models/nasabah.dart';
import 'dart:convert';
import 'package:http/http.dart' show Client;
class ApiService {
final String baseUrl = '192.168.100.242:8080';
Client client = Client();
Future<List<Nasabah>> getNasabah() async {
final response = await client.get('http://$baseUrl/api/mstdebitur');
print(response.body);
if (response.statusCode == 200) {
final nasabah = (json.decode(response.body) as List)
.map((e) => Nasabah.fromMap(e))
.toList();
return nasabah;
} else {
throw Exception('Failed to load post');
}
}
Future<bool> createNasabah(Nasabah data) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/").toString();
final response = await client.post(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 201) {
return true;
} else {
return false;
}
}
Future<bool> updateNasabah(Nasabah data) async {
String url =
new Uri.http("$baseUrl", "/api/mstdebitur/${data.id}").toString();
final response = await client.put(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<bool> deleteNasabah(int id) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/$id").toString();
final response = await client.delete(url);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
}
Home
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'FormAddNasabah.dart';
import 'ListNasabah.dart';
GlobalKey<ScaffoldState> _scaffoldState = GlobalKey<ScaffoldState>();
// ignore: must_be_immutable
class DataNasabah extends StatefulWidget {
DataNasabah({Key key}) : super(key: key);
String title;
#override
_DataNasabahState createState() => _DataNasabahState();
}
class _DataNasabahState extends State<DataNasabah> {
ApiService apiService;
ListNasabah _listNasabah;
List<Nasabah> data;
#override
void initState() {
super.initState();
apiService = ApiService();
_listNasabah = new ListNasabah(apiService: apiService);
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldState,
appBar: AppBar(
title: Text(
'Data Nasabah',
style: TextStyle(color: Colors.white),
),
actions: <Widget>[
GestureDetector(
onTap: () async {
var result = await Navigator.push(
_scaffoldState.currentContext,
MaterialPageRoute(builder: (BuildContext context) {
return FormAddNasabah(nasabah: null);
}),
);
if (result != null) {
setState(() {});
}
},
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Icon(
Icons.add,
color: Colors.white,
),
),
)
],
),
body: _listNasabah.createViewList(),
);
}
}
List
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/FormAddNasabah.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/NasabahHome.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
class ListNasabah {
ApiService apiService;
ListNasabah({this.apiService});
Widget createViewList() {
return SafeArea(
child: FutureBuilder(
future: apiService.getNasabah(),
builder: (BuildContext context, AsyncSnapshot<List<Nasabah>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
'Something wrong with message: ${snapshot.error.toString()}',
textAlign: TextAlign.center,
),
);
} else if (snapshot.connectionState == ConnectionState.done) {
List<Nasabah> nasabah = snapshot.data;
return nasabahListView(nasabah);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Widget nasabahListView(List<Nasabah> listnasabah) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
Nasabah nasabah = listnasabah[index];
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
nasabah.nama_debitur,
style: Theme.of(context).textTheme.bodyText1,
),
Text(nasabah.alamat),
Text(nasabah.no_ktp),
Text(nasabah.no_telp),
Text(nasabah.no_selular),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {
apiService.deleteNasabah(nasabah.id).then((value) =>
Navigator.of(context).pushNamed('start'));
},
child: Text(
"Hapus",
style: TextStyle(color: Colors.red),
),
),
FlatButton(
onPressed: () async {
var result = await Navigator.push(context,
MaterialPageRoute(builder: (context) {
return FormAddNasabah(
nasabah: nasabah,
);
}));
},
child: Text(
'Edit',
style: TextStyle(color: Colors.blue),
),
),
],
)
],
),
),
),
);
},
itemCount: listnasabah.length,
),
);
}
}
Form
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/NasabahHome.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
class FormAddNasabah extends StatefulWidget {
Nasabah nasabah;
FormAddNasabah({this.nasabah});
#override
_FormAddNasabahState createState() => _FormAddNasabahState();
}
class _FormAddNasabahState extends State<FormAddNasabah> {
ApiService apiService;
TextEditingController _contNama = TextEditingController();
TextEditingController _contAlamat = TextEditingController();
TextEditingController _contNoTelp = TextEditingController();
TextEditingController _contNoKtp = TextEditingController();
TextEditingController _contNoSelular = TextEditingController();
#override
void initState() {
super.initState();
apiService = ApiService();
if (widget.nasabah != null) {
_contNama.text = widget.nasabah.nama_debitur;
_contAlamat.text = widget.nasabah.alamat;
_contNoTelp.text = widget.nasabah.no_telp;
_contNoKtp.text = widget.nasabah.no_ktp;
_contNoSelular.text = widget.nasabah.no_selular;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.white),
title: Text(
widget.nasabah == null ? "Tambah Nasabah" : "Edit Nasabah",
style: TextStyle(color: Colors.white),
),
),
body: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
_buildTextField(_contNama, "Nama Nasabah"),
_buildTextField(_contAlamat, "Alamat"),
_buildTextField(_contNoTelp, "No Telp"),
_buildTextField(_contNoKtp, "No KTP"),
_buildTextField(_contNoSelular, "No Selular"),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: RaisedButton(
child: Text(widget.nasabah == null ? "Tambah" : "Edit"),
color: Colors.blue,
onPressed: () {
int id = 0;
if (widget.nasabah != null) {
id = widget.nasabah.id;
}
Nasabah nasabah = Nasabah(
id: id,
nama_debitur: _contNama.text,
alamat: _contAlamat.text,
no_telp: _contNoTelp.text,
no_ktp: _contNoKtp.text,
no_selular: _contNoSelular.text);
if (widget.nasabah == null) {
apiService.createNasabah(nasabah);
} else {
apiService.updateNasabah(nasabah);
}
Navigator.of(context)
.pushNamed('start')
.whenComplete(() => Navigator.pop(context));
},
),
)
],
),
)
],
),
);
}
Widget _buildTextField(TextEditingController _cont, String label) {
return TextField(
controller: _cont,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
}
}
Thank you for your attention!

Obtain coordinates from an address flutter

Could someone guide me to get the coordinates of an address in flutter?
I need to enter addresses in a text box and get the longitude and latitude of that address
You can copy paste run full code below
You can use package https://pub.dev/packages/geocoder
code snippet
import 'package:geocoder/geocoder.dart';
// From a query
final query = "1600 Amphiteatre Parkway, Mountain View";
var addresses = await Geocoder.local.findAddressesFromQuery(query);
var first = addresses.first;
print("${first.featureName} : ${first.coordinates}");
working demo, last line is coordinates
full code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geocoder/geocoder.dart';
import 'package:geocoder/services/base.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class AppState extends InheritedWidget {
const AppState({
Key key,
this.mode,
Widget child,
}) : assert(mode != null),
assert(child != null),
super(key: key, child: child);
final Geocoding mode;
static AppState of(BuildContext context) {
return context.inheritFromWidgetOfExactType(AppState);
}
#override
bool updateShouldNotify(AppState old) => mode != old.mode;
}
class GeocodeView extends StatefulWidget {
GeocodeView();
#override
_GeocodeViewState createState() => new _GeocodeViewState();
}
class _GeocodeViewState extends State<GeocodeView> {
_GeocodeViewState();
final TextEditingController _controller = new TextEditingController();
List<Address> results = [];
bool isLoading = false;
Future search() async {
this.setState(() {
this.isLoading = true;
});
try {
var geocoding = AppState.of(context).mode;
var results = await geocoding.findAddressesFromQuery(_controller.text);
this.setState(() {
this.results = results;
});
} catch (e) {
print("Error occured: $e");
} finally {
this.setState(() {
this.isLoading = false;
});
}
}
#override
Widget build(BuildContext context) {
return new Column(children: <Widget>[
new Card(
child: new Padding(
padding: const EdgeInsets.all(10.0),
child: new Row(
children: <Widget>[
new Expanded(
child: new TextField(
controller: _controller,
decoration: new InputDecoration(hintText: "Enter an address"),
),
),
new IconButton(
icon: new Icon(Icons.search), onPressed: () => search())
],
),
),
),
new Expanded(child: new AddressListView(this.isLoading, this.results)),
]);
}
}
class ReverseGeocodeView extends StatefulWidget {
ReverseGeocodeView();
#override
_ReverseGeocodeViewState createState() => new _ReverseGeocodeViewState();
}
class _ReverseGeocodeViewState extends State<ReverseGeocodeView> {
final TextEditingController _controllerLongitude =
new TextEditingController();
final TextEditingController _controllerLatitude = new TextEditingController();
_ReverseGeocodeViewState();
List<Address> results = [];
bool isLoading = false;
Future search() async {
this.setState(() {
this.isLoading = true;
});
try {
var geocoding = AppState.of(context).mode;
var longitude = double.parse(_controllerLongitude.text);
var latitude = double.parse(_controllerLatitude.text);
var results = await geocoding
.findAddressesFromCoordinates(new Coordinates(latitude, longitude));
this.setState(() {
this.results = results;
});
} catch (e) {
print("Error occured: $e");
} finally {
this.setState(() {
this.isLoading = false;
});
}
}
#override
Widget build(BuildContext context) {
return new Column(children: <Widget>[
new Card(
child: new Padding(
padding: const EdgeInsets.all(10.0),
child: new Row(
children: <Widget>[
new Expanded(
child: new Column(
children: <Widget>[
new TextField(
controller: _controllerLatitude,
decoration: new InputDecoration(hintText: "Latitude"),
),
new TextField(
controller: _controllerLongitude,
decoration: new InputDecoration(hintText: "Longitude"),
),
],
),
),
new IconButton(
icon: new Icon(Icons.search), onPressed: () => search())
],
),
),
),
new Expanded(child: new AddressListView(this.isLoading, this.results)),
]);
}
}
class _MyAppState extends State<MyApp> {
Geocoding geocoding = Geocoder.local;
final Map<String, Geocoding> modes = {
"Local": Geocoder.local,
"Google (distant)": Geocoder.google("<API-KEY>"),
};
void _changeMode(Geocoding mode) {
this.setState(() {
geocoding = mode;
});
}
#override
Widget build(BuildContext context) {
return new AppState(
mode: this.geocoding,
child: new MaterialApp(
home: new DefaultTabController(
length: 2,
child: new Scaffold(
appBar: new AppBar(
title: new Text('Geocoder'),
actions: <Widget>[
new PopupMenuButton<Geocoding>(
// overflow menu
onSelected: _changeMode,
itemBuilder: (BuildContext context) {
return modes.keys.map((String mode) {
return new CheckedPopupMenuItem<Geocoding>(
checked: modes[mode] == this.geocoding,
value: modes[mode],
child: new Text(mode),
);
}).toList();
},
),
],
bottom: new TabBar(
tabs: [
new Tab(
text: "Query",
icon: new Icon(Icons.search),
),
new Tab(
text: "Coordinates",
icon: new Icon(Icons.pin_drop),
),
],
),
),
body: new TabBarView(children: <Widget>[
new GeocodeView(),
new ReverseGeocodeView(),
]),
),
),
),
);
}
}
class AddressTile extends StatelessWidget {
final Address address;
AddressTile(this.address);
final titleStyle =
const TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold);
#override
Widget build(BuildContext context) {
return new Padding(
padding: const EdgeInsets.all(10.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new ErrorLabel(
"feature name",
this.address.featureName,
fontSize: 15.0,
isBold: true,
),
new ErrorLabel("address lines", this.address.addressLine),
new ErrorLabel("country name", this.address.countryName),
new ErrorLabel("locality", this.address.locality),
new ErrorLabel("sub-locality", this.address.subLocality),
new ErrorLabel("admin-area", this.address.adminArea),
new ErrorLabel("sub-admin-area", this.address.subAdminArea),
new ErrorLabel("thoroughfare", this.address.thoroughfare),
new ErrorLabel("sub-thoroughfare", this.address.subThoroughfare),
new ErrorLabel("postal code", this.address.postalCode),
this.address.coordinates != null
? new ErrorLabel("", this.address.coordinates.toString())
: new ErrorLabel("coordinates", null),
]),
);
}
}
class AddressListView extends StatelessWidget {
final List<Address> addresses;
final bool isLoading;
AddressListView(this.isLoading, this.addresses);
#override
Widget build(BuildContext context) {
if (this.isLoading) {
return new Center(child: new CircularProgressIndicator());
}
return new ListView.builder(
itemCount: this.addresses.length,
itemBuilder: (c, i) => new AddressTile(this.addresses[i]),
);
}
}
class ErrorLabel extends StatelessWidget {
final String name, text;
final TextStyle descriptionStyle;
ErrorLabel(this.name, String text,
{double fontSize = 9.0, bool isBold = false})
: this.text = text ?? "Unknown $name",
this.descriptionStyle = new TextStyle(
fontSize: fontSize,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
color: text == null ? Colors.red : Colors.black);
#override
Widget build(BuildContext context) {
return new Text(this.text, style: descriptionStyle);
}
}
Here created an Input Text Widget and when user taps on it. This takes to google autocomplete screen, where user inputs the location.
TextFormField(
decoration: new InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(left: 15),
hintText: Strings.enter_your_house_number_street_etc,
hintStyle: TextStyle(
fontSize: 14,
color: AppColor.grey,
fontFamily: "Open Sans",
fontWeight: FontWeight.normal
)),
maxLines: 1,
controller: _address,
onTap: ()async{
// then get the Prediction selected
Prediction p = await PlacesAutocomplete.show(
context: context, apiKey: kGoogleApiKey,
onError: onError);
displayPrediction(p);
},
)
Here it is getting the lat and long of entered location.
Future<Null> displayPrediction(Prediction p) async {
if (p != null) {
PlacesDetailsResponse detail = await _places.getDetailsByPlaceId(p.placeId);
var placeId = p.placeId;
lat = detail.result.geometry.location.lat;
long = detail.result.geometry.location.lng;
var address =detail.result.formattedAddress;
print(lat);
print(long);
print(address);
setState(() {
_address.text = address;
});
}
}
import 'package:flutter_google_places/flutter_google_places.dart';
We can use the Geo Coder plugin which will use to get lat and lng from a given address.
import 'package:geocoding/geocoding.dart';
List<Location> locations = await locationFromAddress("Gronausestraat 710, Enschede");

Dropdown in flutter from LIST

Displaying the data from my API based on the Dropdown selected value. I want to display on the same page. The data from the server(response) is displaying on the console. But still, this data is not displaying.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
//import 'package:json_parsing_example/model2.dart';
//import 'package:json_parsing_example/models.dart'
List<YouModel> youModelFromJson(String str) => List<YouModel>.from(json.decode(str).map((x) => YouModel.fromJson(x)));
String youModelToJson(List<YouModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class YouModel {
String columnName;
YouModel({
this.columnName,
});
factory YouModel.fromJson(Map<String, dynamic> json) => YouModel(
columnName: json["column_name"],
);
Map<String, dynamic> toJson() => {
"column_name": columnName,
};
}
UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));
String userModelToJson(UserModel data) => json.encode(data.toJson());
class UserModel {
String username;
String name;
UserModel({
this.username,
this.name,
});
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
username: json["username"],
name: json["Name"],
);
Map<String, dynamic> toJson() => {
"username": username,
"Name": name,
};
}
class Addoffers2 extends StatefulWidget {
#override
State<StatefulWidget> createState() => _Addoffers2State();
}
class _Addoffers2State extends State<Addoffers2> {
List<String> _companies = [];
bool _isLoading = false;
String _selectedCompany;
#override
void initState() {
super.initState();
_selectedCompany=null;
_getcompanylist();
}
Future<String> loadFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
_getcompanylist() async {
setState(() {
_isLoading = true;
});
print("getting..");
final responseStr =
await http.get('http://10.0.2.2/Flutter/GetCompanieslist.php');
//String responseStr = await loadFromAssets();
final listData = youModelFromJson(responseStr.body);
for(int i=0;i<listData.length;i++)
{
print('this is the list :'+listData[i].columnName);
// _companies.add(listData[i].columnName);
}
// above method is the standard method to get creating a model class and then get the list of strings
// I have just shown you but example is according to you code .
// this above loadFromAssets is that you hit the api and you get the json string response
// i have created a dummy json file where i can the String.
// Else everything is the same as below you just have to pass the response.body to the json.decode method.
var jsonData = json.decode(responseStr.body);
for (var u in jsonData) {
_companies.add(u.toString().substring(14, u.toString().length - 1));
}
for (int i = 0; i < _companies.length; i++) {
print(_companies[i].toString());
}
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
//double width = MediaQuery.of(context).size.width;
//double height = MediaQuery.of(context).size.height;
return MaterialApp(
//color: Colors.red,
home: Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
backgroundColor: Theme.of(context).backgroundColor,
title: Text("Add.."),
),
body: Container(
color: Colors.blue,
// just put your height i have modified it replace it by height / 8
child: _isLoading
? CircularProgressIndicator()
: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
//MainAxisAlignment: MainAxisAlignment.spaceBetween,
Text('Choose..'),
DropdownButtonHideUnderline(
child: DropdownButton(
// hint: Text('Choose Company'), // Not necessary for Option 1
value: _selectedCompany,
onChanged: (newValue) {
setState(() {
_selectedCompany = newValue;
// here i have taken the boolen variable to show and hide the list if you have not seleted the value from the dropdown the it will show the text and if selected the it will show you the list.
});
print(_selectedCompany);
},
items: _companies.map((company) {
return DropdownMenuItem(
child: new Text(company.toString()),
value: company,
);
}).toList(),
),
),
],
),
),
),
// this is to to check for the initial if string is null then show the text widget.
// else if the value is selected then it will show the listview
_selectedCompany == null
? Text('Select the dropdown value for list to appear.')// sample text you can modify
: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
height: 100,
color: Theme.of(context).backgroundColor,
child: new FutureBuilder(
future: _getUsers(
_selectedCompany), // a Future<String> or null
builder: (BuildContext context,
AsyncSnapshot snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Container(
child: Center(
child: new CircularProgressIndicator(
backgroundColor: Colors.white,
),
));
}
if (snapshot.hasError) {
return Center(
child: new Text(
'Error ${snapshot.error}'),
);
} else {
return Center(
child: Padding(
padding: const EdgeInsets.fromLTRB(
5.0, 8.0, 5.0, 8.0),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder:
(BuildContext context,
int index) {
List<UserModel> user =
snapshot.data;
var username =
user[index].username;
var stuname =
user[index].name;
print(
'This is the user name :$username');
print(
'This is the name : $stuname');
//var title=snapshot.data[index]["Title"];
// new Text(parsedDate.toString());
return StudentList2(
regdNo: username,
name: stuname);
}),
),
);
}
}),
),
),
],
)),
)),
);
}
}
Future<String> loadFromAssets2() async {
return await rootBundle.loadString('json/parse2.json');
}
// the above method is just for the sample purpose where you get you json String after hitting the api call for _getUsers method
Future<List<UserModel>> _getUsers(String selectedcompany) async {
// here you call you api and you get the response
var url = 'https://10.0.2.2/Flutter/getstudentdata.php;
var data = { 'company': selectedcompany};
// Starting Web Call with data.
var response = await http.post(url, body: json.encode(data));
print(response.body);
//String responseStr = await loadFromAssets2();
final userModel = userModelFromJson(response.body);
// I have just made the model class for where fromt he below you get the complete object and then added to the list and returned.
List<UserModel> users = [];
users.add(userModel);
print('This is the name : ${users[0].name}'); // Even this also not getting printed
return users;
}
class StudentList2 extends StatefulWidget {
final regdNo;
final name;
const StudentList2({
Key key,
this.regdNo,
this.name,
}) : super(key: key);
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<StudentList2> {
bool visible = false;
#override
Widget build(BuildContext context) {
print(widget.regdNo.toString());
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: new Card(
color: Theme.of(context).primaryColor,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 2.0),
child: Container(
child: new Text(
widget.regdNo.toUpperCase(),
style: TextStyle(
color: Colors.yellowAccent,
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
),
),
),
ListTile(
title: new Text(
widget.regdNo,
style: TextStyle(
color: Colors.black,
fontSize: 14.0,
),
),
subtitle: new Text(
(widget.name),
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
),
),
),
//
],
)),
);
}
}
I am able to retrieve the data from the server and print it on the console. Still, the data is not displaying. I do not know where I did the mistake.
So I have completely updated the answer and there are many things that you don't follow according to the global standard.
So I have listed some of the key things that you should follow :
Following is you company list json :
[
{
"column_name": "ABC"
},
{
"column_name": "XYZ"
}
]
Following is the get user json that you will get :
{"username":"1111","Name":"ABC" }
And Later the model class I have create accordingly to the json that you provided and then you can create your own based in the added json.
There are Two model classes that I have created :
First model class is for the company :
// To parse this JSON data, do
//
// final youModel = youModelFromJson(jsonString);
import 'dart:convert';
List<YouModel> youModelFromJson(String str) => List<YouModel>.from(json.decode(str).map((x) => YouModel.fromJson(x)));
String youModelToJson(List<YouModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class YouModel {
String columnName;
YouModel({
this.columnName,
});
factory YouModel.fromJson(Map<String, dynamic> json) => YouModel(
columnName: json["column_name"],
);
Map<String, dynamic> toJson() => {
"column_name": columnName,
};
}
second mode class is for the user :
// To parse this JSON data, do
//
// final userModel = userModelFromJson(jsonString);
import 'dart:convert';
UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));
String userModelToJson(UserModel data) => json.encode(data.toJson());
class UserModel {
String username;
String name;
UserModel({
this.username,
this.name,
});
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
username: json["username"],
name: json["Name"],
);
Map<String, dynamic> toJson() => {
"username": username,
"Name": name,
};
}
Below is the main ui file just Check the comments that I have made so that it will be helpful for you .
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:json_parsing_example/model2.dart';
import 'package:json_parsing_example/models.dart';
void main() => runApp(Addoffers());
class Addoffers extends StatefulWidget {
#override
State<StatefulWidget> createState() => _AddoffersState();
}
class _AddoffersState extends State<Addoffers> {
List<String> _companies = [];
bool _isLoading = false;
String _selectedCompany;
#override
void initState() {
super.initState();
_selectedCompany=null;
_getcompanylist();
}
Future<String> loadFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
_getcompanylist() async {
setState(() {
_isLoading = true;
});
print("getting..");
/* final response =
await http.get('http://10.0.2.2/Flutter/GetCompanieslist.php'); */
String responseStr = await loadFromAssets();
final listData = youModelFromJson(responseStr);
for(int i=0;i<listData.length;i++)
{
print('this is the list :'+listData[i].columnName);
// _companies.add(listData[i].columnName);
}
// above method is the standard method to get creating a model class and then get the list of strings
// I have just shown you but example is according to you code .
// this above loadFromAssets is that you hit the api and you get the json string response
// i have created a dummy json file where i can the String.
// Else everything is the same as below you just have to pass the response.body to the json.decode method.
var jsonData = json.decode(responseStr);
for (var u in jsonData) {
_companies.add(u.toString().substring(14, u.toString().length - 1));
}
for (int i = 0; i < _companies.length; i++) {
print(_companies[i].toString());
}
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
//double width = MediaQuery.of(context).size.width;
//double height = MediaQuery.of(context).size.height;
return MaterialApp(
//color: Colors.red,
home: Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
backgroundColor: Theme.of(context).backgroundColor,
title: Text("Add.."),
),
body: Container(
color: Colors.blue,
// just put your height i have modified it replace it by height / 8
child: _isLoading
? CircularProgressIndicator()
: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
//MainAxisAlignment: MainAxisAlignment.spaceBetween,
Text('Choose..'),
DropdownButtonHideUnderline(
child: DropdownButton(
// hint: Text('Choose Company'), // Not necessary for Option 1
value: _selectedCompany,
onChanged: (newValue) {
setState(() {
_selectedCompany = newValue;
// here i have taken the boolen variable to show and hide the list if you have not seleted the value from the dropdown the it will show the text and if selected the it will show you the list.
});
print(_selectedCompany);
},
items: _companies.map((company) {
return DropdownMenuItem(
child: new Text(company.toString()),
value: company,
);
}).toList(),
),
),
],
),
),
),
// this is to to check for the initial if string is null then show the text widget.
// else if the value is selected then it will show the listview
_selectedCompany == null
? Text('Select the dropdown value for list to appear.')// sample text you can modify
: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
height: 100,
color: Theme.of(context).backgroundColor,
child: new FutureBuilder(
future: _getUsers(
_selectedCompany), // a Future<String> or null
builder: (BuildContext context,
AsyncSnapshot snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Container(
child: Center(
child: new CircularProgressIndicator(
backgroundColor: Colors.white,
),
));
}
if (snapshot.hasError) {
return Center(
child: new Text(
'Error ${snapshot.error}'),
);
} else {
return Center(
child: Padding(
padding: const EdgeInsets.fromLTRB(
5.0, 8.0, 5.0, 8.0),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder:
(BuildContext context,
int index) {
List<UserModel> user =
snapshot.data;
var username =
user[index].username;
var stuname =
user[index].name;
print(
'This is the user name :$username');
print(
'This is the name : $stuname');
//var title=snapshot.data[index]["Title"];
// new Text(parsedDate.toString());
return StudentList2(
regdNo: username,
name: stuname);
}),
),
);
}
}),
),
),
],
)),
)),
);
}
}
Future<String> loadFromAssets2() async {
return await rootBundle.loadString('json/parse2.json');
}
// the above method is just for the sample purpose where you get you json String after hitting the api call for _getUsers method
Future<List<UserModel>> _getUsers(String selectedcompany) async {
/* var data = await http.post("http://10.0.2.2/Flutter/getstdata.php", body: {
"company": selectedcompany,
//print(data.body);
}); */
// here you call you api and you get the response
String responseStr = await loadFromAssets2();
final userModel = userModelFromJson(responseStr);
// I have just made the model class for where fromt he below you get the complete object and then added to the list and returned.
List<UserModel> users = [];
users.add(userModel);
print('This is the name : ${users[0].name}');
//final x=users.length.toString();
//debugPrint("records:" + users.length.toString());
//debugPrint("kkk:" + absentees.length.toString());
return users;
}
class StudentList2 extends StatefulWidget {
//MyHomePage(String branch);
final regdNo;
final name;
const StudentList2({
Key key,
this.regdNo,
this.name,
}) : super(key: key);
//final String branch;
//const StudentList({Key key, this.branch}) : super(key: key);
//MyHomePage(String branch);
// final String title;
// final String branch="";
// MyHomePage(String branch, {Key key, this.title}) : super(key: key);
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<StudentList2> {
bool visible = false;
//bool _btnEnabled = false;
//bool _validate = false;
// var _firstPress = true ;
//Color _iconColor = Colors.yellow;
//Color _iconColor2 = Colors.white;
//var poll;
//DateTime parsedDate;
#override
Widget build(BuildContext context) {
print(widget.regdNo.toString());
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: new Card(
color: Theme.of(context).primaryColor,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 2.0),
child: Container(
child: new Text(
widget.regdNo.toUpperCase(),
style: TextStyle(
color: Colors.yellowAccent,
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
),
),
),
ListTile(
title: new Text(
widget.regdNo,
style: TextStyle(
color: Colors.black,
fontSize: 14.0,
),
),
subtitle: new Text(
(widget.name),
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
),
),
),
//
],
)),
);
}
}
// This is not the good approach to create a model class just check the sample model class that i have created.
class User {
//final int index;
final String username;
final String name;
//final Float cgpa;
User(
this.username,
this.name,
);
}
And below is the sample Gif file for you :
As stated by #pskink the method _getcompanylist() is async. An async function runs asynchronously, which means that the rest of the program doesn't wait for it to complete. You can use a future builder to deal whit that or you can simply wait for it by using the await function. I believe that for your code snippet future builder is the better choice.

Failed assertion: line 4774 pos 14: '_dependents.isEmpty': is not true

I am new to Flutter and I am working on a chat app, and whenever i choose an user i should be able to talk to him in a private way, that's what I am doing, whenever i click someone I try to move to this Chat Screen, and then I am getting this error (see title).
But when I'm pressing the back button and try again it works and shows the chat like it should, this is really confusing me, and if someone have an idea where it comes from, it would be awesome.
Here's my chat.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:social/responsive/size_config.dart';
var _firestore = Firestore.instance;
FirebaseUser loggedInUser;
String groupChatId;
class Chat extends StatelessWidget {
static const String id = 'chat_screen';
final String peerEmail;
Chat({Key key, #required this.peerEmail}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'CHAT',
style: TextStyle(fontWeight: FontWeight.bold),
),
centerTitle: true,
),
body: ChatScreen(peerEmail: peerEmail));
}
}
class ChatScreen extends StatefulWidget {
final String peerEmail;
ChatScreen({this.peerEmail});
#override
_ChatScreenState createState() => _ChatScreenState(peerEmail: peerEmail);
}
class _ChatScreenState extends State<ChatScreen> {
final _auth = FirebaseAuth.instance;
final messageTextController = TextEditingController();
String peerEmail;
String messageText;
_ChatScreenState({this.peerEmail});
#override
void initState() {
super.initState();
getCurrentUser();
String email = loggedInUser.email;
getGroupId(email);
}
void getGroupId(String email) {
if (peerEmail.hashCode <= email.hashCode) {
setState(() {
groupChatId = '$peerEmail-$email';
});
} else {
setState(() {
groupChatId = '$email-$peerEmail';
});
}
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser();
if (user != null) {
loggedInUser = user;
setState(() {});
}
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
MessageStream(),
Container(
decoration: BoxDecoration(color: Colors.red,borderRadius: BorderRadius.circular(10)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
//Do something with the user input.
messageText = value;
},
),
),
FlatButton(
onPressed: () {
//Implement send functionality.
messageTextController.clear();
print(messageText);
print(loggedInUser.email);
_firestore.collection('messages')
.document(groupChatId)
.collection(groupChatId).add({
'content': messageText,
'emailFrom': loggedInUser.email,
'emailTo': peerEmail,
});
},
child: Text(
'Send',
),
),
],
),
),
],
)));
}
}
class MessageStream extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: _firestore
.collection('messages')
.document(groupChatId)
.collection(groupChatId)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.black),
),
);
} else {
final messages = snapshot.data.documents;
List<MessageDisplay> messageList = [];
for (var msg in messages) {
final message = msg.data['content'];
final emailTo = msg.data['emailTo'];
final emailFrom = msg.data['emailFrom'];
final messageDisplay = MessageDisplay(
message: message,
emailFrom: emailFrom,
emailTo: emailTo,
);
messageList.add(messageDisplay);
}
return Expanded(
child: ListView(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: messageList != null ? messageList:CircularProgressIndicator(),
),
);
} //
},
);
}
}
class MessageDisplay extends StatelessWidget {
MessageDisplay({this.message, this.emailFrom, this.emailTo});
final String message;
final String emailFrom;
final String emailTo;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(SizeConfig.safeBlockVertical * 3),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
message != null
? Text(
message,
style: TextStyle(
fontSize: SizeConfig.safeBlockVertical * 15,
color: Colors.black54,
),
)
: CircularProgressIndicator(),
emailFrom != null
? Text(
emailFrom,
)
: CircularProgressIndicator(),
],
),
);
}
}
Thanks for reading.
The most likely cause for this type of error is the new screen you are navigating to is trying to access information from the previous screen which it has no access to or has not inherited and therefore doesn't have the correct build context when trying to build causing this error.