How to get JSON response after onPresseed button in Flutter // Dart - flutter

I don't get any issues to get JSON data the button is pressed to get JSON response.body is printed successfully but the JSON response is executed before I give _addressController value the if condition executed so the exception is shown on the print state. so please see my code and help me to overcome the issues
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:core';
import 'dart:convert';
import 'package:http/http.dart'as http;
import 'string.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Retrieve Text Input',
home: MyCustomForm(),
);
}
}
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
var url1 = 'This is my first off url';
var _addressControler = TextEditingController();
late Future<Balance> futureBalance;
#override
void initState() {
super.initState();
futureBalance = fetchBalance();
}
Future<Balance> fetchBalance() async {
http.Response response =
await http.get(Uri.parse(url1+_addressControler.text));
print(response.body);
if (response.statusCode == 200) {
return Balance.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load album');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: Center(
key: _formKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
controller: _addressControler,
decoration: InputDecoration(
labelText: 'Enter the address...',
labelStyle: TextStyle(color: Colors.blue),
border: new OutlineInputBorder(
borderSide: new BorderSide(color: Colors.black)),),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () async {
await fetchBalance();
},
child: const Text('Submit'),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text("${_addressControler.text}"),
),
Container(
//color: Colors.blueAccent,
child: FutureBuilder<Balance>(
future: futureBalance,
builder: (context, index) {
if (index.hasData) {
print(index.data!.height);
var x = (index.data!.result[0].amount);
var y = int.parse(x);
assert(y is int);
var z = (y / 1000000);
print(z);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('${z.toString()}',
style: TextStyle(fontSize: 20,),),
]);
} else if (index.hasError) {
return Text("${index.error}");
}
return CircularProgressIndicator();
},
),
),
]
),
),
)
);
}
}
I have an issue on fetchBalance() function. The if the condition is executed before I click the onPressed button but I what to do after given TextField and submit onPressed to execute the condition. so, is any possible way to overcome this issue please help me...

I am not sure I understand your question, but it seems you get an error because fetchBalance is executed before you expect it to.
Well, you call futureBalance = fetchBalance(); within your initState() method, hence the code is executed when your widget is being initialized and not only after you press the button. This means, you try to parse the url without appending _addressControler.text.

also, you can use it like this.
fetchBalance().then((balance) {
setState(() {
_balance = balance; //need to create one variable of type Balance
});
});

Better put the setState() in your async call:
Future<Balance> fetchBalance() async {
http.Response response =
await http.get(Uri.parse(url1+_addressControler.text));
print(response.body);
if (response.statusCode == 200) {
setState(() {
_balance = Balance.fromJson(jsonDecode(response.body));
});
} else {
throw Exception('Failed to load album');
}
}

First up all I remove the initState() and i use setState() for onPressed() to call the API function fetchBalance() on the state it's working good..
child: ElevatedButton(
onPressed: () {
setState(() {
fetchBalance();
});
fetchBalance();
},
child: const Text('Submit'),
),
),

Related

API data not showing in flutter dropdown

i am trying to display data list API to dropdown but the result is not there, which i have to fix.
I'm trying to change or update user data and have some data in the form of a list including the user being able to choose country, religion, and others. among these
how do i make it.
fetch API
Future<UserBiodata> getBiodata() async {
String url = Constant.baseURL;
String token = await UtilSharedPreferences.getToken();
final response = await http.get(
Uri.parse(
'$url/auth/mhs_siakad/biodata',
),
headers: {
'Authorization': 'Bearer $token',
},
);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
return UserBiodata.fromJson(jsonDecode(response.body));
} else {
throw Exception('Token Expired!');
}
}
show in widget
String? _mySelection;
List<Agama> agama = [];
#override
void initState() {
super.initState();
BiodataProvider().getBiodata();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: CustomAppbar(
title: 'Edit Biodata',
),
),
body: Padding(
padding: const EdgeInsets.all(18),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(left: 12, right: 8),
width: double.infinity,
height: 50,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 9,
offset: const Offset(
1,
2,
),
),
],
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
items: agama.map((item) {
return DropdownMenuItem<String>(
value: item.nmAgama,
child: Text(item.nmAgama),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelection = newVal!;
});
},
value: _mySelection,
),
),
),
using StateManagement or FutureBuilder to receive async data from Future function (BiodataProvider().getBiodata();)
read more at: https://dart.dev/codelabs/async-await
https://docs.flutter.dev/development/data-and-backend
you are using List<Agama> agama = []; to display the dropdown items, but you are not adding data to your agama list.
So, add the proper data into your agama list which you are getting from API.
And don't forget to do setState((){}) after adding data into agama list because you are not using any state management.
Here is a full example like you want.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter DropDownButton',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String? dropdownvalue;
Future<List<String>> getAllCategory() async {
var baseUrl = "https://gssskhokhar.com/api/classes/";
http.Response response = await http.get(Uri.parse(baseUrl));
if (response.statusCode == 200) {
List<String> items = [];
var jsonData = json.decode(response.body) as List;
for (var element in jsonData) {
items.add(element["ClassName"]);
}
return items;
} else {
throw response.statusCode;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("DropDown List"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FutureBuilder<List<String>>(
future: getAllCategory(),
builder: (context, snapshot) {
if (snapshot.hasData) {
var data = snapshot.data!;
return DropdownButton(
// Initial Value
value: dropdownvalue ?? data[0],
// Down Arrow Icon
icon: const Icon(Icons.keyboard_arrow_down),
// Array list of items
items: data.map((String items) {
return DropdownMenuItem(
value: items,
child: Text(items),
);
}).toList(),
// After selecting the desired option,it will
// change button value to selected value
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
});
},
);
} else {
return const CircularProgressIndicator();
}
},
),
],
),
),
);
}
}

Assistance needed with flutter app saving user authentication status

I have an app where Users can currently log in (using phone auth) and log out from the home screen. But whenever the app gets refreshed the user logs out automatically.
What I want to do is to keep the user logged in till he pressed the log out button.
Since I am new to flutter and coding in general it would be helpful if you can help me with the exact code.
main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'login.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Firebase.initializeApp();
runApp(const MaterialApp(
home: MyApp(),
debugShowCheckedModeBanner: false,
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return const LoginScreen();
}
}
login.dart
import 'package:flutter/material.dart';
import 'otp.dart';
import 'package:intl_phone_field/intl_phone_field.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
String Country = '';
final TextEditingController _controller2 = TextEditingController();
final TextEditingController _controller = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Phone Auth'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(children: [
Container(
margin: const EdgeInsets.only(top: 60),
child: const Center(
child: Text(
'Phone Authentication',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 28),
),
),
),
//Phone feild
IntlPhoneField(
decoration: const InputDecoration(
labelText: 'Phone Number',
border: OutlineInputBorder(
borderSide: BorderSide(),
),
),
controller: _controller,
initialCountryCode: 'IN',
onChanged: (phone) {
debugPrint('Below is phone number');
debugPrint(phone.completeNumber);
debugPrint('Country code is: ${phone.countryCode}');
Country = phone.countryCode;
// phone.countryCode = _controller2 as String;
debugPrint(Country);
},
),
// Container(
// margin: const EdgeInsets.only(top: 40, right: 10, left: 10),
// child: TextField(
// decoration: const InputDecoration(
// hintText: 'Phone Number',
// prefix: Padding(
// padding: EdgeInsets.all(4),
// child: Text('+91'),
// ),
// ),
// maxLength: 10,
// keyboardType: TextInputType.number,
// controller: _controller,
// ),
// )
]),
Container(
margin: const EdgeInsets.all(10),
width: double.infinity,
child: FlatButton(
color: Colors.blue,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
OTPScreen(_controller.text, Country)));
},
child: const Text(
'Next',
style: TextStyle(color: Colors.white),
),
),
)
],
),
);
}
}
otp.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
import 'package:pinput/pinput.dart';
class OTPScreen extends StatefulWidget {
final String phone;
final String countryCode;
const OTPScreen(this.phone, this.countryCode, {Key? key}) : super(key: key);
#override
_OTPScreenState createState() => _OTPScreenState();
}
class _OTPScreenState extends State<OTPScreen> {
final GlobalKey<ScaffoldState> _scaffoldkey = GlobalKey<ScaffoldState>();
late String _verificationCode;
final TextEditingController _pinPutController = TextEditingController();
final FocusNode _pinPutFocusNode = FocusNode();
final BoxDecoration pinPutDecoration = BoxDecoration(
color: const Color.fromRGBO(43, 46, 66, 1),
borderRadius: BorderRadius.circular(10.0),
border: Border.all(
color: const Color.fromRGBO(126, 203, 224, 1),
),
);
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldkey,
appBar: AppBar(
title: const Text('OTP Verification'),
),
body: Column(
children: [
Container(
margin: const EdgeInsets.only(top: 40),
child: Center(
child: Text(
'Verify ${widget.countryCode} ${widget.phone}',
style:
const TextStyle(fontWeight: FontWeight.bold, fontSize: 26),
),
),
),
Padding(
padding: const EdgeInsets.all(30.0),
child: Pinput(
length: 6,
// fieldsCount: 6,
// textStyle: const TextStyle(fontSize: 25.0, color: Colors.white),
// eachFieldWidth: 40.0,
// eachFieldHeight: 55.0,
// focusNode: _pinPutFocusNode,
// controller: _pinPutController,
// submittedFieldDecoration: pinPutDecoration,
// selectedFieldDecoration: pinPutDecoration,
// followingFieldDecoration: pinPutDecoration,
// pinAnimationType: PinAnimationType.fade,
onSubmitted: (pin) async {
debugPrint('submit pressed');
try {
await FirebaseAuth.instance
.signInWithCredential(PhoneAuthProvider.credential(
verificationId: _verificationCode, smsCode: pin))
.then((value) async {
if (value.user != null) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => Home()),
(route) => false);
}
});
} catch (e) {
FocusScope.of(context).unfocus();
_scaffoldkey.currentState!.showSnackBar(
const SnackBar(content: Text('invalid OTP')));
}
},
),
)
],
),
);
}
_verifyPhone() async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: '${widget.countryCode}${widget.phone}',
verificationCompleted: (PhoneAuthCredential credential) async {
await FirebaseAuth.instance
.signInWithCredential(credential)
.then((value) async {
if (value.user != null) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => Home()),
(route) => false);
}
});
},
verificationFailed: (FirebaseAuthException e) {
debugPrint(e.message);
},
codeSent: (String verficationID, int? resendToken) {
setState(() {
_verificationCode = verficationID;
});
},
codeAutoRetrievalTimeout: (String verificationID) {
setState(() {
_verificationCode = verificationID;
});
},
timeout: const Duration(seconds: 120));
}
#override
void initState() {
// TODO: implement initState
super.initState();
_verifyPhone();
}
}
home.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'login.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
late String uid;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
IconButton(
icon: const Icon(Icons.logout),
onPressed: () async {
await FirebaseAuth.instance.signOut();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const LoginScreen()),
(route) => false);
},
)
],
),
body: Center(
child: Text(uid),
),
);
}
#override
void initState() {
// TODO: implement initState
super.initState();
uid = FirebaseAuth.instance.currentUser!.uid;
}
}
One perfect way is to store the data in shared preferences. All you need in to add the flutter shared_preference package [https://pub.dev/packages/shared_preferences].
CONFIGURATION
After adding this package, create a shared_preference object like: * final preference = await SharedPreference.getInstance*
Next you can store the logs on the mobile storage using the preference object. For example, to store a variable isAuthenticated(which stores the authentication as bool) status of the user, do something like: * await preference.setBool("authentication", isAuthenticated)*
Step three, create another method to retrieve the data from storage.
first create another preference object loke in step one(1). But this time instead of setBool, use getBool like:* final isAlreadyAuthenticated = preferences.getBool("authentication")*
Now isAleadyAuthenticated holds the value whether is user already login or not and can you can use it to display a login screen of the value is false
Since you are using firebase, i recommed you add the firebase_auth package. And then you wrap the MyApp with a stream builder and supply FirebaseAuth.instance.authStateChanges as stream to the stream parameter which comes with the firebase_auth
So in the builder of the stream builder, return the MyApp() if snapshot.hasData, else return the OTP screen

flutter The expression doesn't evaluate to a function, so it can't be invoked

am trying to do a login screen to my application and I wanted to make a loading screen using flutter spinkit but there s always an error in my loading function
the error is at the return loading ? loading() The expression doesn't evaluate to a function, so it can't be invoked
if anyone can help me It would be great and thank you in advance
// ignore_for_file: use_key_in_widget_constructors, prefer_const_literals_to_create_immutables, prefer_const_constructors, unused_import, non_constant_identifier_names
import 'dart:ffi';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:myapp2/loading.dart';
import 'package:myapp2/second.dart';
import 'dart:convert';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Login(),
);
}
}
class Login extends StatefulWidget {
#override
LoginPage createState() => LoginPage();
}
class LoginPage extends State<Login> {
var emailControler = TextEditingController();
var passControler = TextEditingController();
bool Loading = false;
#override
Widget build(BuildContext context) {
return Loading
? Loading()
: Scaffold(
body: Padding(
padding: const EdgeInsets.all(10.0),
child: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: emailControler,
obscureText: false,
decoration: InputDecoration(
labelText: "Email",
border: OutlineInputBorder(),
suffixIcon: Icon(Icons.email)),
),
SizedBox(
height: 15,
),
TextFormField(
controller: passControler,
obscureText: true,
decoration: InputDecoration(
labelText: "Password",
border: OutlineInputBorder(),
suffixIcon: Icon(Icons.lock)),
),
SizedBox(
height: 45,
),
OutlinedButton.icon(
onPressed: () {
Login();
},
icon: Icon(
Icons.login,
size: 18,
),
label: Text("login")),
],
)),
),
),
);
}
// base64 encoding a string
encode() {
String credentials = emailControler.text + ":" + passControler.text;
Codec<String, String> stringToBase64 = utf8.fuse(base64);
String encoded = stringToBase64.encode(credentials);
return (encoded);
}
//Login POST API CALL
Future<void> Login() async {
if (passControler.text.isNotEmpty && emailControler.text.isNotEmpty) {
setState(() => Loading = true);
var response = await http.post(
Uri.parse(""),
headers: ({
'MAXAUTH': encode(),
}));
if (response.statusCode == 200) {
setState(() => Loading = true);
Navigator.push(
context, MaterialPageRoute(builder: (context) => Second()));
} else {
setState(() => Loading = false);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Invalid cords!")));
}
} else {
setState(() => Loading = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Empty fields are not allowed !")));
}
}
}
loading is defined as a boolean in your code. It can't be used as a widget! The naming convention is to use camelCase/lowercase when defining variables to avoid confusion.
Change
bool Loading = false;
To
bool loading = false;
Then update your code:
return loading
? Center(
child: SpinKitRotatingCircle(
color: Colors.blue,
size: 50.0,
),
);
: Scaffold(
body: Padding(

The return type 'NewsModel' isn't a 'Widget' as required by the closure's context

I have been trying to build a News App that fetches data from the newsapi.org service and just when I am about to call the data inside the main method I am getting this error saying that my class 'NewsModel' isn't of the type 'Widget' as required by the closure's context. I have no idea what that means but here is my code for the app split into 2 files.
import 'package:flutter/material.dart';
import 'models/news_model.dart';
import 'news_service.dart';
import 'package:assgn_digia_tech/models/news_model.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _loading = true;
var newsList;
List<NewsModel> articles = [];
void getNews() async {
newsService apiNews = newsService();
await apiNews.getNews();
articles = apiNews.apiNews;
setState(() {
_loading = false;
});
}
#override
void initState() {
super.initState();
getNews();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
'News API',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
backgroundColor: Colors.cyan[50],
// ignore: prefer_const_literals_to_create_immutables
actions: [
Padding(
padding: const EdgeInsets.only(right: 12.0),
child: IconButton(
icon: Icon(Icons.search, color: Colors.black, size: 26),
onPressed: () {},
),
),
],
),
body: SafeArea(
child: _loading
? Center(
child: CircularProgressIndicator(),
)
: SingleChildScrollView(
child: Container(
child: Column(
children: [
Container(
child: ListView.builder(
itemCount: articles.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return NewsModel(
title: articles[index].title,
description: articles[index].description,
author: articles[index].author,
content: articles[index].content,
urlToImage: articles[index].urlToImage,
);
},
),
),
],
),
),
),
),
),
);
}
}
import 'dart:convert';
import 'package:assgn_digia_tech/models/news_model.dart';
import 'package:http/http.dart' as http;
class newsService {
List<NewsModel> apiNews = [];
Future<void> getNews() async {
String apiUrl =
'https://newsapi.org/v2/top-headlines?country=in&apiKey=4e3474bb91ec49eda31b75e2daf6da3c';
var response = await http.get(Uri.parse(apiUrl));
var jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
jsonData['articles'].forEach((element) {
if (element['urlToImage'] != null && element['description'] != null) {
NewsModel article = NewsModel(
title: element['title'],
author: element['author'],
description: element['description'],
urlToImage: element['urlToImage'],
content: element["content"],
);
apiNews.add(article);
}
});
}
}
}
itemBuilder: (context, index) {
return NewsModel(
You are supposed to return a Widget from the builder, because the purpose is to build a UI. Do you have a custom "NewsWidget" here, or do you want to build it from scratch? Maybe start by returning Text(articles[index].title) and then building it up from there to include all the other parts of your NewsModel.

Create table from imported data

I am trying to create a table from an imported CSV file, that I can latter call upon for data. I followed this tutorial here as a starting point.
So far I have managed to create the table, but it only generates once you press a button. What I would like to do is for the table to be loaded as soon as the app starts.
My code is almost identical to the one in the tutorial, but either way, here it is:
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
class TableLayout extends StatefulWidget {
const TableLayout({Key key}) : super(key: key);
#override
_TableLayoutState createState() => _TableLayoutState();
}
class _TableLayoutState extends State<TableLayout> {
List<List<dynamic>> data = [];
loadAsset() async {
final myData = await rootBundle.loadString("assets/routes.csv");
List<List<dynamic>> csvTable = const CsvToListConverter().convert(myData);
print(csvTable);
data = csvTable;
setState(() {
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.refresh),
onPressed: () async {
await loadAsset();
//print(data);
}),
appBar: AppBar(
title: const Text("Bus Routes"),
),
body: SingleChildScrollView(
child: Table(
border: TableBorder.all(width: 1.0),
children: data.map((item) {
return TableRow(
children: item.map((row) {
return Container(
color: Colors.blueGrey,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Text(
row.toString(),
style: const TextStyle(fontSize: 20.0),
),
),
);
}).toList());
}).toList(),
),
),
);
}
}
With this code, the following screen is generated (once you push the button):
I'm not worried about the look of the table as the user wont actually be seeing it in the end. Instead it will be used to retrieve data for use in other screens of my app. I understand that it is only generated on the button press because of this line:
onPressed: () async {
await loadAsset();
I am unsure on how to run this when the app starts rather than when the button is pressed.
Solution:
Thanks to rosh-dev's comment I was able to create a initSate to fix my problem.
This tutorial also helped: Flutter Tutorial for Beginners #25 - Asynchronous Code
The new code looks like this:
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
class TableLayout extends StatefulWidget {
const TableLayout({Key key}) : super(key: key);
#override
_TableLayoutState createState() => _TableLayoutState();
}
class _TableLayoutState extends State<TableLayout> {
List<List<dynamic>> data = [];
void loadAsset() async {
final myData = await rootBundle.loadString("assets/routes.csv");
List<List<dynamic>> csvTable = const CsvToListConverter().convert(myData);
print(csvTable);
data = csvTable;
setState(() {
});
}
#override
void initState() {
super.initState();
loadAsset();
}
Widget build(BuildContext context) {
return Scaffold(
// floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
// floatingActionButton: FloatingActionButton(
// child: const Icon(Icons.refresh),
// onPressed: () async {
// await loadAsset();
// }),
appBar: AppBar(
title: const Text("Bus Routes"),
),
body: SingleChildScrollView(
child: Table(
border: TableBorder.all(width: 1.0),
children: data.map((item) {
return TableRow(
children: item.map((row) {
return Container(
color: Colors.blueGrey,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Text(
row.toString(),
style: const TextStyle(fontSize: 20.0),
),
),
);
}).toList());
}).toList(),
),
),
);
}
}
Thanks