I have GetxController with the late Map data and I won't fill this in onInit() after searching on the database, but when the page is open the emulator shows the red screen with the not initialize error.
I need the dataMap1 and 2 for showing the PieChart when the screen opens.
I think this occurred because I use the Future function, But I do not know how to fix this.
this is my entire controller code.
import 'package:get/get.dart';
import 'package:hive/hive.dart';
class ReportScreenController extends GetxController{
late Map<String, double> dataMap1;
final Map<String, double> dataMap2 = {
"ورزشی": 5,
"خصوصی": 3,
"اداری": 5,
"دسته بندی نشده": 3,
};
#override
Future<void> onInit() async {
super.onInit();
//categoryScrollController.position.ensureVisible()
await reportFunction();
}
Future<void> reportFunction() async {
//dataMap1
var taskBox = await Hive.openBox('task');
var taskFinish =
taskBox.values.where((task) => task.status == true).toList();
var taskUnFinish =
taskBox.values.where((task) => task.status == false).toList();
double test = double.parse(taskFinish.length.toString());
double test2 = double.parse(taskUnFinish.length.toString());
print(test.toString());
print(test2.toString());
dataMap1.addAll({
'رو زمین مانده': test2,
'تکمیل شده': test,
});
}
}
my view code is
class ReportScreen extends GetView<ReportScreenController> {
const ReportScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
background(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: Column(
children: [
const Text(':نمودار فعالیت', style: boldText),
MyPieChart(dataMap: controller.dataMap1),
const Text(':نمودار وظایف', style: boldText),
MyPieChart(dataMap: controller.dataMap2),
],
),
),
],
),
);
}
}
You forgot to initialize dataMap1, simply in onInit() add dataMap1 = {}.
I think you also dont need a late modifier, just use final final Map<String, double> dataMap1 = {};, but everybody is choosing thier weapons.
In addition i think there will be problem with that how you use controller.dataMap1 in your view. Most likely you dont rebuild your view after you finally initialize / populate dataMap1.
Update:
You can change in controller:
late Map<String, double> dataMap1; to final RxMap<String, double> dataMap1 = RxMap();, and in your view:
MyPieChart(dataMap: controller.dataMap1), to Obx(() => MyPieChart(dataMap: controller.dataMap1.value))
Related
Please someone help. Here is my code. Why is not the output of the API (stored in parse) showing in the UI in the blue container. Thanks.
import 'dart:convert';
import 'package:api/model/pin_code.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Map parse = <dynamic,dynamic>{};
Future<dynamic> getPincode(String pincode) async {
var response = await http
.get(Uri.parse('https://api.postalpincode.in/pincode/${pincode}'));
return compute(parsePinCode, response.body);
}
List<PinCode> parsePinCode(String responseBody) {
final parse = jsonDecode(responseBody);
print(parse);
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
final yourResponse = parsed.map<PinCode>((json) => PinCode.fromJson(json)).toList();
print('Here you go ${parsed[0]["PostOffice"][0]["Name"]}');
return yourResponse;
}
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
final TextEditingController pinCode = TextEditingController();
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text('Pin code Rest API Demo '),
),
body: Column(
children: [
SizedBox(height: height * 0.09),
TextFormField(
controller: pinCode,
),
SizedBox(
height: height * 0.05,
),
ElevatedButton(
onPressed: () async {
print("DATA FETCHED ${pinCode.text}");
final mapResponse = getPincode(pinCode.text);
print(mapResponse.toString());
},
child: const Text("Search")),
Container(
color: Colors.blue,
child: Text('Here you go $parse'),
)
],
),
);
}
}
I tried putting parse as a global variable but didn't get the API's output rendered in the UI despite calling it in the scaffold's container that I want to render it in.
In method parsePinCode, you assigned json value in local variable parse
Change from final parse = jsonDecode(responseBody); to parse = jsonDecode(responseBody);
I am building a simple calculator and using Riverpod for state management. Though I can update state, the UI is not being updated with the changes... Can someone tell me what I'm doing wrong ?? Here's the code:
Calculator Model
class CalculatorModel {
final bool shouldAppend;
final String equation;
final String result;
const CalculatorModel(
{this.shouldAppend = true, this.equation = '0', this.result = '0'});
CalculatorModel copyWith({
bool? shouldAppend,
String? equation,
String? result,
}) =>
CalculatorModel(
shouldAppend: shouldAppend ?? this.shouldAppend,
equation: equation ?? this.equation,
result: result ?? this.result);
}
Calculator State Notifier Implementation
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:components/calculator_components/calculator_model.dart';
import 'package:math_expressions/math_expressions.dart';
final calculatorProvider =
StateNotifierProvider<CalculatorStateNotifier, List<CalculatorModel>>(
(ref) => CalculatorStateNotifier());
class CalculatorStateNotifier extends StateNotifier<List<CalculatorModel>> {
CalculatorStateNotifier() : super([const CalculatorModel()]);
void append(String calcInput) {
final equation = () {
return state[0].equation == '0'
? calcInput
: state[0].equation + calcInput;
}();
state[0] = CalculatorModel(equation: equation);
}
}
Click function for calculator buttons. State is getting updated, successfully...
void onClickedButton(String calcInput, WidgetRef ref) {
ref.read(calculatorProvider.notifier).append(calcInput);
ref.watch(calculatorProvider);
print(ref.watch(calculatorProvider)[0].equation);
}
Riverpod not updating UI when called in the presentation layer...
#override
Widget build(BuildContext context, WidgetRef ref) {
Size size = MediaQuery.of(context).size;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
margin: const EdgeInsets.symmetric(vertical: 10),
width: size.width * 0.8,
child: Column(children: [
Expanded(
child: Container(
child: Padding(
padding: const EdgeInsets.only(top: 15.0, right: 22),
child: Consumer(builder: (context, ref, _) {
return buildCalculatorScreen(
ref.watch(calculatorProvider)[0].equation,
ref.watch(calculatorProvider)[0].result);
}),
)),
),
]),
);
}
}
First, you should not use ref.watch on asynchronous calls, including button calls.
Second, Since our state is immutable, we are not allowed to do state[0] = . You need to update your List in some other way, such as using the spread operator or List.of()
More information here:
StateNotifierProvider from Riverpod
state should be immutable, you have to set a new object/array as the new state.
You can do something like this:
final newState = List.from(state);
newState[0] = CalculatorModel(equation: equation);
state = newState;
I want to update the RangeSlider values from the database. but I don't know how to do this please help to show and update the RangeSlider values from the database. I have two values from the database for RangeSlider to start and end which i set in getData() data but when I initialize the values in Rnageslider it gives me the error The argument type 'RangeValues?' can't be assigned to the parameter type 'RangeValues'. and also in RangeLabels(_currentRangeValues.start.round().toString(),_currentRangeValues.end.round().toString(),)
In RangeLabels it gives me an error:- The property 'start' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!'). and same for end
values:- _currentRangeValues = RangeValues(data[0]['age1'], data[0]['age2']);
values which comes from databse:- 20 60 in getDData() function
here is my code:-
class Age extends StatefulWidget {
Age({Key? key}) : super(key: key);
#override
_Age createState() => _Age();
}
class _Age extends State<Age >{
var UsrID = Auth.prefs?.getString('usrid');
var data;
RangeValues? _currentRangeValues;
#override
void initState() {
super.initState();
getData();
}
getData() async{
var res = await http.get(Uri.https('www.*******.com',
'/index.php',{'act':'profile','UsrID': '${UsrID}'}));
data = jsonDecode(res.body);
print(data);
_currentRangeValues = RangeValues(data[0]['age1'], data[0]['age2']);
setState(() {});
print(res.body);
}
//RangeValues _currentRangeValues = RangeValues(30, 70);
#override
Widget build(BuildContext context){
return Scaffold(
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Age',
style: TextStyle(
color: Color(0xff2c3531),
),
),
addVerticalSpace(10),
RangeSlider(
activeColor: Color(0xff8f9df2),
inactiveColor: Color(0xff9a9a9a),
values: _currentRangeValues!,
max: 100,
divisions: 5,
labels: RangeLabels(
_currentRangeValues!.start.round().toString(),
_currentRangeValues!.end.round().toString(),
),
onChanged: (RangeValues? values) {
setState(() {
_currentRangeValues = values;
});
},
),
],
),
)
}
Anyone, please help how to initialize dynamic data in `RangeValues
Here is error in RangeSlider() widget :-
You have to use Nullable types to avoid this issue.
change RangeValue to RangeValue?.
and you have to use ! at _currentRangeValue!.start.round().toString()
you can find more info on null safety Here
My expectation from ReoderableListView.builder() is simply, as what the Flutter doc says, to create a widget that allows users to move/drag list-items up and down the list view. However, what I was getting from my emulator was no dragging animation, no reordering of the list (upon user input), and not even call to the onReorder callback.
Stuff I have tried:
Made sure my taskID and taskName lists have the same length
Added debug outputs for itemBuilder and onReorder callback, surprisingly receiving debug output only from itemBuilder callback
Copied and pasted the widget code and its corresponding lists data exactly to other widget classes (or files) and still got the same result
Added the exactly same ValueKey in the Text() inside the list-view.
Tried using the same list data as what the Text() is rendering, taskNames, for the value ValueKey
The only thing I did not try was directly copying and pasting the official example of this widget to my codebase, but the test code I have should already be very similar to the official example, structurally.
checklist.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'add_task.dart';
class Checklist extends StatefulWidget {
const Checklist({Key? key}) : super(key: key);
#override
State<Checklist> createState() => _ChecklistState();
}
class _ChecklistState extends State<Checklist> {
final List<int> taskID = <int>[0, 1, 2, 4, 6];
final List<String> taskNames = <String>['A', 'B', 'C', 'D', 'E'];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
children: [
const Text("TODO"),
ElevatedButton(
onPressed: () {
},
child: const Text("Google Calendar"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.black12),
),
),
]
),
),
body: ReorderableListView.builder(
itemCount: taskNames.length,
itemBuilder: (BuildContext context, int index) {
print("B");
return ListTile(
key: ValueKey(taskID[index]),
tileColor: Colors.black12,
title: Text('Entry ${taskNames[index]}')
);
},
onReorder: (int oldIndex, int newIndex) {
print("A");
setState(() {
if (newIndex > oldIndex) {
newIndex -= 1;
}
final int elTid = taskID.removeAt(oldIndex);
final String elTnm = taskNames.removeAt(oldIndex);
taskID.insert(newIndex, elTid);
taskNames.insert(newIndex, elTnm);
});
},
),
);
}
}
Your code does work. It moves only on long press and drag. Not on normal drag.. On normal drag it will tend to scroll the list
I'm having this super annoying issue of being unable to grab and display a table from my server hosted on PhpmyAdmin. (I've managed to grab the data and have it printed in the console, but now that I'm trying to display it in a table I can't seem to get it working)
I've tried nulling my variables but I'm not really sure what the main culprit for this error is. Any help would be greatly appreciated.
Image of Error
data.dart File
class dataListing extends StatefulWidget {
const dataListing({Key? key}) : super(key: key);
#override
State<dataListing> createState() => _dataListingState();
}
class _dataListingState extends State<dataListing> {
#override
Widget build(BuildContext context) {
return Container();
}
}
class listingData{
String? ListingID, listingName, listingDescription, address, suburbName, phoneNumber, openingHours, Email, Website;
listingData({
this.ListingID,
this.listingName,
this.listingDescription,
this.address,
this.suburbName,
this.phoneNumber,
this.openingHours,
this.Email,
this.Website,
});
//constructor
List<listingData> datalist = [];
factory listingData.fromJSON(Map<String, dynamic> json){
return listingData(
ListingID: json["ListingID"],
listingName: json["listingName"],
listingDescription: json["listingDescription"],
address: json["address"],
suburbName: json["suburbName"],
phoneNumber: json["phoneNumber"],
openingHours: json["openingHours"],
Email: json["Email"],
Website: json["Website"],
);
}
}
Directory.dart file
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:app/pages/data.dart';
class directoryPage extends StatefulWidget {
#override
State<directoryPage> createState() => _directoryPageState();
}
class _directoryPageState extends State<directoryPage> {
// List serviceListing = [];
//
// getAllListing()async{
// String url = "URL HERE";
// var response = await http.get(Uri.parse(url));
// if (response.statusCode == 200){
// setState (() {
// serviceListing = json.decode(response.body);
// });
// print (serviceListing);
// return serviceListing;
// }
// }
bool error = false, dataloaded = false;
var data;
String dataurl = "URL HERE";
#override
void initState (){
loaddata();
super.initState();
// getAllListing();
}
void loaddata() {
Future.delayed(Duration.zero,() async {
var res = await http.post(Uri.parse(dataurl));
if (res.statusCode == 200) {
setState(() {
data = json.decode(res.body);
dataloaded = true;
});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Directory'),
centerTitle: true,
elevation: 0,
backgroundColor: Color(0xFFA30B32),
//WSU Appbar Icon
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset("assets/wsulogo.png", scale: 8.0),
),
),
body: Container(
padding: EdgeInsets.all(15),
child:dataloaded?datalist():
Center(
child:CircularProgressIndicator()
),
)
);
}
Widget datalist(){
if(data["error"]) {
return Text(data["errmsg"]);
}else{
List<listingData> datalist = List<listingData>.from(data["data"].map((i){
return listingData.fromJSON(i);
})
);
return Table( //if data is loaded then show table
border: TableBorder.all(width:1, color:Colors.black45),
children: datalist.map((listingdata){
return TableRow( //return table row in every loop
children: [
//table cells inside table row
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.ListingID!)
)
),
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.listingName!)
)
),
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.listingDescription!)
)
),
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.address!)
)
),
]
);
}).toList(),
);
}
}
}
Looks like the issue was actually unrelated to the dart side of things, the php code wasn't properly structuring the data. Cannot have underscores or spaces.
Correct-> $json["dballlisting"] = array (); (I renamed it to just "data" later)
Incorrect->$json["db_all_listing"] = array ();
The error seems to be originating from this line, the data['data'] is null which is expected to be an Array.
List<listingData> datalist = List<listingData>.from(data["data"].map((i){
return listingData.fromJSON(i);
})
You need to investigate your API call to make sure why it is happening. If the null value is expected then you need to add safeguards in your code to make sure it won't break when it encounter such scenarios. You can add null safety checks for that one way to do it would be to
List<listingData> datalist = List<listingData>.from((data["data"] ?? []).map((i){
return listingData.fromJSON(i);
})