Flutter pass json data to new Stateful Widget - android

I pass json data to new stateful widget in flutter. I can see data is not null in the debug console but stateful widget receive null data.
I tried other passing data type but still doesn't work.
How can I fix this? Any Help
Here is the code
Navigator Code
void goToFilteredList() async {
jsonData =await postQuotationFilteredList(
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
false,
false,
null,
null);
print(jsonData);
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FilteredQuotationList(jsonData)));
}
Stateful Widget
class FilteredQuotationList extends StatefulWidget {
final List<Map<String, dynamic>> jsonData;
FilteredQuotationList(this.jsonData);
static const String routeName = "/filteredquotationlist";
#override
State<StatefulWidget> createState() =>
FilteredQuotationListScreen(this.jsonData);
}
jsonData has same type and there is the cons and this code received null data.
class FilteredQuotationListScreen extends State<FilteredQuotationList> {
List<Map<String, dynamic>> jsonData;
FilteredQuotationListScreen(List<Map<String, dynamic>> jsonData) {
this.jsonData = jsonData;
}
#override
Widget build(BuildContext context) {
print("filtreleme ekranı");
print(jsonData);
return Scaffold(
body: quotationFilteredListItems(jsonData),
);
}
ListView quotationFilteredListItems(List<Map<String, dynamic>> jsonData) {
print("quotation filtered list items");
List<GetQuotationModel> getQuotationModel =
GetQuotationModel.fromJson(jsonData);
print(getQuotationModel.length);
return ListView.builder(
itemCount: 3,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.amberAccent,
elevation: 2.0,
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.green,
child: Text("getQuotationModel.quoteNumber"),
),
title: Text("this."),
),
);
},
);
}
}

First of all, this isn't how you should be using stateful widgets that are provided data via their constructor. Basically, the State object can access any parameter of the Widget object for free.
Here is an example of how it should be used.
class MyWidget extends StatefulWidget {
MyWidget({
Key key,
#required this.myParameter,
}) : super(key: key);
final String myParameter;
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
#override
Widget build(BuildContext context) {
return Text(widget.myParameter); // the widget accessor is included in every State
}
}
And then using it would look like this:
#override
Widget build(BuildContext context) {
return MyWidget(myParameter: "Hurray!");
}
Let me know if this fixes the issues you're having.

Related

I get a null error when I try to run my flutter app after trying to fetch data from a url

I get the error below after modifying my home page on my app to the code as shown below, I get the error in my object_patch.dart file. I don't know how that can be resolved. what could I have done wrong?
Exception has occurred.
NoSuchMethodError (NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: ) (see image)
import 'package:awsome_app/drawer.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class Homepage extends StatefulWidget {
const Homepage({Key? key}) : super(key: key);
#override
State<Homepage> createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
//Functions here now
// var myText = "This is a function";
// TextEditingController _nameController = TextEditingController();
var url = "https://jsonplaceholder.typicode.com/photos";
var data;
#override
void initState() {
// TODO: implement initState
super.initState();
fetchData();
}
fetchData() async {
var res = await http.post(Uri.parse(url));
data = jsonDecode(res.body);
setState(() {});
;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromARGB(204, 255, 249, 249),
appBar: AppBar(title: const Text("Welcome to Flutter App")),
body: data != null
? ListView.builder(
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index]["title"]),
);
},
itemCount: data.length,
)
: Center(
child: CircularProgressIndicator(),
)
);
}
}```
GET https://jsonplaceholder.typicode.com/photos will return a list of photos.
Replace
var res = await http.post(Uri.parse(url));
with
var res = await http.get(Uri.parse(url));

type 'List<dynamic>' is not a subtype of type 'List<Widget>' How do I use a List<Dynamic> in a listview widget?

I am trying to use a list in a Listview widget in flutter but I keep getting an error saying that I need a List[Widget]. All the answers online make use of maps and I am still a beginner to Flutter. Can anyone show me how to use the map function for this or a way to convert List [Dynamic] to List [Widget]?
Here is my code:
import 'package:flutter/material.dart';
class NextPage extends StatefulWidget {
final List value;
NextPage({Key key, this.value}) : super(key: key);
#override
_NextPageState createState() => new _NextPageState();
}
class _NextPageState extends State<NextPage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Reminders"),
),
body: ListView(
children: widget.value,
),
);
}
}
According to the discussion, value is List<String> in that case, to pass it on ListView we need to use these data and convert them into widget.
Here we are using value and making Text widget with it
import 'package:flutter/material.dart';
class NextPage extends StatefulWidget {
final List<String> value;
NextPage({Key key, this.value}) : super(key: key);
#override
_NextPageState createState() => new _NextPageState();
}
class _NextPageState extends State<NextPage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Reminders"),
),
body: ListView(
children: widget.value.map((e) => Text(e)).toList(),
),
);
}
}
Does it solve the issue?

Checking one CheckBox in a ListView checks all of the rest using Flutter

I am completly new to Flutter and Stackoverflow. This is my first question to be in fact so please forgive me if I totaly fail at asking this question. I am trying to make a simple Flutter app that provides a ListView of questions and a checkbox beside each. The user can then choose which question they want to answer. My problem is that when the user checks any of the checkboxes then all get checked and vise versa. The questions themselves are retrieved from a backendless database. The code below is what i have so far. I would really appreciate any help anyone can provide me.
import 'package:flutter/material.dart';
class Questions extends StatefulWidget {
final List<Map> questionList;
Questions(this.questionList);
#override
_QuestionsState createState() => _QuestionsState();
}
class _QuestionsState extends State<Questions> {
bool _questionSelected = true;
Widget _buildQuestionItem(BuildContext context, int index) {
return ListTile(
title: Text(widget.questionList[index]['question']),
trailing: Checkbox(
value: _questionSelected,
onChanged: (bool val){
setState(() {
_questionSelected = val;
});
},
),
);
}
#override
Widget build(BuildContext context) {
return ListView.builder(
padding: EdgeInsets.all(10),
itemBuilder: _buildQuestionItem,
itemCount: widget.questionList.length,
);
}
}
UPDATED:
Thankful for Mohammed Ashab Uddin suggestions I feel that I am close to getting this thing to work but I am still getting an error
"RangeError (index): Invalid value: Valid value range is empty: 0"
I think I should have posted the main.dart code where I set the value of the questionList perhaps it is an order of code execution that causes this error so please find my code for main.dart below in hopes it would help in figuring out this issue.
import 'package:flutter/material.dart';
import 'package:backendless_sdk/backendless_sdk.dart';
import 'package:flutter/rendering.dart';
import 'questions.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'RT Database Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Questions'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
static const String API_HOST = "https://api.backendless.com";
static const String APP_ID = "<APP_ID>";
static const String ANDROID_APP_KEY = "<ANDROID_APP_KEY>";
static const String IOS_APP_KEY = "<IOS_APP_KEY>";
IDataStore<Map> questionsStore = Backendless.data.of('Questions');
List<Map> questionsList = [];
var _questionSelected = false;
#override
void initState() {
super.initState();
_initBackendless();
_enableRealTime();
getQuestions();
}
void _initBackendless() {
Backendless.setUrl(API_HOST);
Backendless.initApp(APP_ID, ANDROID_APP_KEY, IOS_APP_KEY);
}
void _enableRealTime() {
EventHandler<Map> rtHandlers = questionsStore.rt();
rtHandlers.addCreateListener((question) {
setState(() {
questionsList = List.from(questionsList);
questionsList.add(question);
});
});
rtHandlers.addUpdateListener((question) {
setState(() {
questionsList = List.from(questionsList
.map((m) => m['objectId'] == question['objectId'] ? question : m));
});
});
rtHandlers.addDeleteListener((question) {
setState(() {
questionsList = List.from(questionsList);
questionsList.removeWhere((m) => m['objectId'] == question['objectId']);
});
});
}
void _selectQuestion(bool newValue) {
setState(() {
_questionSelected = newValue;
});
}
void getQuestions() {
DataQueryBuilder queryBuilder = DataQueryBuilder()
..pageSize = 100
..sortBy = ['created'];
questionsStore
.find(queryBuilder)
.then((response) => setState(() => questionsList = response));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("My Life History"),
),
body: FractionallySizedBox(
heightFactor: 0.5,
child: Questions(questionsList),
),
);
}
}
The variable _questionSelected is a global variable. All the checkbox widgets are using this variable as the value. Therefore, when the variable changes on the onChanged() function, all the values are also changed to the value of _questionSelected.
In this case, you need to keep track of all the values of the checkbox widget. So, you should use an array rather than a single variable.
What I usually do is, create a new list that will contain only the selected elements.
Remove an element if it is not selected and add an element if it is selected.
//generate a list of false values with the length of questionList
List<bool> _questionSelected;
initState(){
_questionSelected = List<bool>.filled(questionList.length, false, growable: true);
super.initState();
}
Widget _buildQuestionItem(BuildContext context, int index) {
return ListTile(
title: Text(widget.questionList[index]['question']),
trailing: Checkbox(
value: _questionSelected[index],
onChanged: (bool val){
setState(() {
_questionSelected[index] = val;
});
},
),
);
}

How to send and receive arguments between views in flutter

I'm trying to send data from a page to another in flutter project, tried all methods I found in another question but all failed, here is my code :
The first page :
Navigator.pushNamed(context, '/line_details', arguments: {'line':line,});
The second page:
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}
note: the line is a custom object created.
the error : always returns null, even when tried to send a single string as {"test": "test string"} it returns a null too
your Example is working fine
route in MaterialApp
routes: { "/line_details": (context) => LineDetails(), },
Push on FlatButton:
onPressed: () => Navigator.pushNamed(context, '/line_details', arguments: {'line':'test',}),
class LineDetails
class LineDetails extends StatefulWidget {
#override
_LineDetailsState createState() => _LineDetailsState();
}
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments;
print(data);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}
with GestureDetector is also working
new GestureDetector(
onTap: () => Navigator.pushNamed(context, '/line_details', arguments: {'line':'test',}),
child: new Container(child: new Text("GestureDetector"),),
),
try this:
Navigator.push(
context,
LineDetailsState(
builder: (context) => LineDetailsState(
line: line
)))
and
class LineDetailsState extends StatefulWidget {
LineDetailsState(this.line);
Line line;
#override
_LineDetailsState createState() => _LineDetailsState();
}
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}
instead of "Line" replace it with name of your custom object
Your example looks proper one other thing you can try is typecast your argument
like below which help dart for linting. Note this is not related that you are getting null
class LineDetails extends StatefulWidget {
#override
_LineDetailsState createState() => _LineDetailsState();
}
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments as Map<String,object>;
print(data);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}

Navigator.pop won't close the simpledialog in flutter

I'm building android app using flutter. I have a problem to close the simple dialog programmatically.
Now I have a stateful page named ListVessel. This page contains listTile from array otherVessels.
Below is the code for this page.
class ListVessel extends StatefulWidget {
final Function() notifyParent;
ListVessel({Key key, #required this.notifyParent}) : super(key: key);
#override
_ListVesselState createState() => _ListVesselState();
}
class _ListVesselState extends State<ListVessel> {
#override
Widget build(BuildContext context) {
return ListView.separated(
separatorBuilder: (context, index) => Divider(color: Colors.blueGrey),
itemCount: otherVessels.length,
itemBuilder: (context, index) {
return ListTile(
title: Text("Name: "+otherVessels[index]["shipName"]),
onTap: () {
showDialog (
context: context,
builder: (_){
return otherTap(idx:index);
}
);
}
);
},
);
}
}
}
From above code, each tile (vessel) can be tapped and it calls otherTap() method. otherTap() method displays a simple dialog (popup) that contains the details of the tapped vessel.
Below is the code for otherTap().
class otherTap extends StatefulWidget{
otherTap({Key key, #required this.idx}) : super(key: key);
final int idx;
#override
_otherTapState createState() => new _otherTapState();
}
class _otherTapState extends State<otherTap>{
#override
Widget build(BuildContext context){
_isDialogShowing = true;
return SimpleDialog(
title: Text(otherVessels[widget.idx]["shipName"]),
children: <Widget>[
SimpleDialogOption(
child: Text('MMSI : ' + otherVessels[widget.idx]['MMSI']),
)
],
);
}
}
I have a global boolean variable (_isDialogShowing) to keep tracking if the dialog is showing.
Now i want the showdialog (popup) to dismiss after 5 second.
I use Navigator.pop() to dismiss the dialog in the MyApp function. I put it inside setstate() function.
void main() {
runApp(
MyApp(storage: CounterStorage()),
);
}
class MyApp extends StatefulWidget {
MyApp({Key key, #required this.storage}) : super(key: key);
final CounterStorage storage;
#override
State<StatefulWidget> createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
final appTitle = 'Testing applicatin';
void _update(BuildContext context) async {
await Future.delayed(Duration(milliseconds: 5000));
setState(() {
if(_isDialogShowing){
_isDialogShowing = false;
Navigator.pop(context);
//Navigator.of(context).pop();
}
});
}
#override
Widget build(BuildContext context) {
_update(context);
return new WillPopScope(
onWillPop: null,
child: new MaterialApp(
debugShowCheckedModeBanner: false,
title: appTitle,
home: MyHomePage(title: appTitle),
routes: {
Routes.home: (context) => MyHomePage(),
Routes.settings: (context) => SettingsPage(),
},
),
);
}
}
However the navigator.pop methods above doesn't close the popup.
Can anyone help?
You need to call pop on the context that you receive in builder of showDialog(), only then the dialog will pop that was created by that showDialog().
Replace your showDialog() with following and it will work for you:
showDialog(
context: context,
builder: (BuildContext context) {
Future.delayed(Duration(seconds: 5)).then((_) {
Navigator.pop(context);
});
return otherTap(idx:index);
},
);
I've solved this issue using
Navigator.of(context, rootNavigator: true).pop();

Categories

Resources