There is an order list(contains orders) which is configured with pageview builder(Horizontal scroll) and in each order page there are items in listview.builder(vertical scroll), which I am able to successfully configure dynamically.
Now every order has n number of items, and each item has an button, which calls for action successfully. Now after the successful action, I want the order item in a order for which the action was executed should be removed from the listview.builder, because it gets removed in the server backend.
And when the order has no items left, it should be removed from the pageview.builder as well, because it is also removed from the server.
the code I am using is below for the widget of pageview.builder and list.viewbuilder
FutureBuilder(
future: _future,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.content.length,// length of total orders
itemBuilder: (context, index) {
var firstdata = jsonResponse['content'];
var list = firstdata[index]['order_items'];
return Column(
children:<Widget>[
Text( firstdata[index]['order_no]),
ListView.builder(
shrinkWrap: true,
itemCount: //lenght of the items in the order to be determined,
itemBuilder: (context, index) {
return Column(
children: [
Text(list[index]['item_number']),
RaisedButton(
onPressed: (){
callaction();
},
)
],
);
},
),
])
});
}
}
})
Function called
callaction(){
print('action called on server');
var response = await http.post(url, body: data);
if (response.statusCode == 200) {
print('success');
}
}
Please guide me on how should I achieve the desired functionality. json flutter indexing flutter-listview flutter-pageview
You could pass the index of the firstdata's item to callaction(). The problem is that the second builder's index is shadowing the first, so you need to rename at least one of the two. Then you can do callaction(firstIndex) and from there, remove the correct item from firstdata.
Related
I already connect and get data from MQTT broker using snapshot method. However, I want to convert the MQTT message to JSON format cause I want to do some condition code to certain data.
My problem is when I stream data from the MQTT broker, my data only came out for the last data for that index. That index consists three different data, but since the index hold 3 data at the same time, only the last data of the index that displayed. This is my current code. How can I do that?
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter MQTT"),
),
body: FutureBuilder(
future: mqttSubscribe(topic: "/sensor_simulator/data"),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
return Center(
child: Text("Error: ${snapshot.error}"),
);
}
// if succeed to connect
if (snapshot.connectionState == ConnectionState.done) {
return StreamBuilder(
stream: snapshot.data,
builder: (BuildContext context, AsyncSnapshot snapshot) {
// if have error--> display
if (snapshot.hasError) {
return Center(
child: Text("Error: ${snapshot.error}"),
);
}
// if data detected--> display
if (snapshot.hasData) {
try {
final List<MqttReceivedMessage> receiveMessage =
snapshot.data;
final recMess =
receiveMessage[0].payload as MqttPublishMessage;
String payload = MqttPublishPayload.bytesToStringAsString(
recMess.payload.message);
return ListView(
children: [
Card(
child: ListTile(
title: Text(payload),
))
],
padding: EdgeInsets.all(10),
);
} catch (e) {
return Center(
child: Text("Error: ${e.toString()}"),
);
}
}
return Center(child: CircularProgressIndicator());
},
);
}
return Center(child: CircularProgressIndicator());
},
),
);
}
}
You can use this piece of code:
void _subscribeToTopic(String topicName) {
print('MQTTClientWrapper::Subscribing to the $topicName topic');
client.subscribe(topicName, MqttQos.atMostOnce);
client.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final recMess = c[0].payload as MqttPublishMessage;
String message =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
String decodeMessage = Utf8Decoder().convert(message.codeUnits);
print("MQTTClientWrapper::GOT A NEW MESSAGE $decodeMessage");
});
}
I am working on a test application in Dart. The application is used for displaying and inserting data into a database hosted with 000webhost.com
I am displaying my json data into a table in my app. I would like all the columns to be inside of one table. With my current code it is displaying every column inside of a brand new table
like shown here:
Below is the relevant code for my project:
class ViewData extends StatelessWidget{
final String url = 'https://fourieristic-thousa.000webhostapp.com/index.code.php?action=view';
Future<List<dynamic>> fetchData() async {
var result = await http.get(
Uri.parse(url),
);
print(json.decode(result.body));
return json.decode(result.body);
}
// First entry of each column.
String _test(dynamic test, int index){
return test[index]['testColumn'];
}
// Second entry of each column.
int _test2(dynamic test, int index){
return json.decode(test[index]['testColumn2']);
}
// Third entry of each column (Will some day be a delete function)
int _id(dynamic test, int index){
return json.decode(test[index]['ID']);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test data table'),
),
body: Container(
child: FutureBuilder<List<dynamic>>(
future: fetchData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.hasData){
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: const <DataColumn>[
DataColumn(
label: Text(
'Test',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Test2',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Delete',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
],
rows: <DataRow>[
DataRow(
cells: <DataCell>[
DataCell(
Text(_test(snapshot.data, index).toString())
),
DataCell(
Text(_test2(snapshot.data, index).toString())
),
DataCell(
Text(_id(snapshot.data, index).toString())
)
],
),
],
),
);
}
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
),
);
}
}
I have tried looking for an answer online with no result. I have also tried rewriting my code to attempt to find anything wrong with it. I understand why the app is showing the data in individual tables, but I can not find a way to fix it.
You claim to know what the problem is so I won't go in depth, but the main issue is your ListView.builder; there is no reason to have it there. Instead, you should replace the code between if(snapshot.hasData){ and return SingleChildScrollView( with something like this:
List<DataRow> dataRows = [];
for (var index = 0; index < snapshot.data.length; index++) {
dataRows.add(
DataRow(
cells: <DataCell>[
DataCell(
Text(_test(snapshot.data, index).toString())
),
DataCell(
Text(_test2(snapshot.data, index).toString())
),
DataCell(
Text(_id(snapshot.data, index).toString())
),
],
),
);
}
and then put the dataRows variable in the rows: field of your DataTable. Your tree should end up being Scaffold -> Container -> FutureBuilder -> SingleChildScrollView -> DataTable. This way you won't be building a new table for every entry.
a sample of what i have in mind
var url = 'https://www.googleapis.com/books/v1/volumes?q=egg';
Future<BookResponse> getData() async {
var response = await http.get(url);
var responseBody = jsonDecode(response.body);
// print(responseBody);
return BookResponse.fromJson(responseBody);
}
-----
FutureBuilder<BookResponse>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) print(snapshot.error);
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.items.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title:
Text(snapshot.data.items[index].volumeInfo.title),
));
});
} else
return Center(child: CircularProgressIndicator());
},
)
im trying to create a method that will convert json map into a List<widgets> so i can use it to display items.
i can't find a way to display items as rows and columns.
is it possible to have multiple widgets using FutureBuilder? (one row of books and another row to show authors for example)
if so i will avoid converting it to List<widgets>
Convert JSON data to objects and:
Row(
children: entities.map((entity) => Text(entity.text)).toList();
),
It creates a list with widgets.
I am having difficulty with data get. I am very new to Flutter and although I read the articles, I could not overcome this problem. I was able to get the data individually, but I couldn't put it in a loop. The codes are below.
Future<List<Post>> getPosts() async {
var jsonData = await http.get("https://example.com/api/posts.php");
final jsonResponse = json.decode(jsonData.body);
Match postList= Post.fromJsonMap(jsonResponse);
return (jsonResponse as List)
.map((postList) => Post.fromJsonMap(postList))
.toList();
//print("post" + postList.result[1].home);
}
When I run the print method, I can print the data. However, when I send it to futurebuilder, the data is not coming.
body: FutureBuilder(
future: getPosts(),
builder: (BuildContext context, AsyncSnapshot<List<Post>> snapshot) {
if (snapshot.hasData) {
print("test");
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index].result[index].home),
subtitle: Text(snapshot.data[index].result[index].title),
leading: CircleAvatar(
child: Text(
snapshot.data[index].result[index].id.toString()),
),
);
});
} else {
return Center(child: CircularProgressIndicator());
}
}),
Note: The codes I used as an example: https://github.com/emrealtunbilek/flutter_json_http/blob/master/lib/remote_api.dart
Try add additional if branch like this
} else if (snapshot.hasError) {
print(snapshot.error);
} else {
You can use JsonToDart for parse data and cast to your model
I'm working on flutter app in which I want to show feeds, I want to show 1st list(Horizontal list) with 4 workouts, 2nd list (Vertical list) with 4 posts, 3rd list (Horizontal list) with 4 coaches and 4th list again 4 posts. At the end of list there is 'Load More' button and after click on button again repeating 1st step i.e. 4 workouts, 4 Posts, 4 Coaches and 4 Posts. My question is What is the best way to display this type of view.
Video For clear my points
Here is an example of what you want to achieve:
List<List<String>> lists = [["A1","A2","A3","A4","A5"],["B1","B2","B3"],["C1","C2","C3","C4","C5"],["D1","D2","D3"]];
Widget buildCard(String text) {
return Container(
margin: EdgeInsets.all(4.0),
padding: EdgeInsets.all(40.0),
alignment: Alignment.center,
color: Colors.lightGreenAccent,
child: Text(text),
);
}
Widget buildHorizontalList(List<String> sublist) {
return SizedBox(
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: sublist.length,
itemBuilder: (context, index) => buildCard("${sublist[index]}"),
),
);
}
Widget buildVerticalList(List<String> sublist) {
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: sublist.length,
itemBuilder: (context, index) {
return buildCard("${sublist[index]}");
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: lists.length + 1,
itemBuilder: (context, index) {
if (index <= lists.length - 1) {
return index.isEven ? buildHorizontalList(lists[index]) : buildVerticalList(lists[index]);
}
return RaisedButton(
child: Text('Load More'),
onPressed: () {
setState(() {
lists.addAll([["X1","X2","X3","X4","X5"],["Y1","Y2","Y3"]]);
});
},
);
}),
);
}
Edit: I added the Load More button functionality, basically the button just update the 'lists' variable (a list that contains all the sublists). Then the ListViews are being build according to the 'lists' content.
Can't you, instead of showing every listview within another listview, just show it all within a SingleChildScrollView, and then just add all the listviews to a row widget.
SingleChildScrollView(
child: Column(
children<widget>[
// Put listviews here.
],
),
),