When I click on the button, I need its name to be added to the List and when the button is clicked again, its name is added to the List again, but if 2 names match in the List, then they both need to be deleted. I tried to implement through the for loop but it does not work correctly for me. Tell me how can this be done?
function
List<String> types = [];
void reportButton(int number, String type) {
reportsList[number] = !reportsList[number];
if (reportsList.contains(true)) {
isEnabledC = true;
} else {
isEnabledC = false;
}
types.add(type);
for (var element in types) {
if (element == type) {
types.removeWhere((element) => element == type);
}
}
buttons
SizedBox(
width: size.width / 3,
child: GestureDetector(
onTap: () {
cubit.reportButton(0, 'comment');
// state.type = 'comment';
},
child: ReportButton(
enabled: state.reports[0],
svg: constants.Assets.comment,
text: 'Comment',
),
),
),
SizedBox(
width: size.width / 3,
child: GestureDetector(
onTap: () {
cubit.reportButton(1, 'broken');
// state.type = 'broken';
},
child: ReportButton(
enabled: state.reports[1],
svg: constants.Assets.attention,
text: 'Broken station',
),
),
),
you do not have to loop through the list of string. You can simply check if the list contains the string. If yes, remove it, else add the string
List<String> types = ["apple", "ball", "cat", "dog"];
void main() async {
reportButton(1, "xyz");
}
void reportButton(int number, String type) {
if (types.contains(type)) {
types.removeWhere((element) => element == type);
} else {
types.add(type);
}
print(types);
}
List<String> types = ["boy", "girl", "father", "hog"];
void main() {
reportButton(1, "xyz");
}
void reportButton(int number, String type) {
if (types.contains(type)) {
types.removeWhere((element) => element == type);
}else {
types.add(type);
}
print(types);
}
Related
When I am calling getUserById() function everything works fine and the growable string works fine but when I use the same variable inside a text widget then it shows RangeError.
The problem is occuring only when I try to use a growable list of string named as dataAsString inside the build.
Here is the Code with Error. Go to the scaffold where I have commented the line of error
import 'package:Healthwise/helpers/user.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../helpers/backEnd.dart';
import '../helpers/frontEnd.dart';
class ResultPage extends StatefulWidget {
const ResultPage({Key? key}) : super(key: key);
#override
State<ResultPage> createState() => _ResultPageState();
}
class _ResultPageState extends State<ResultPage> {
// String docId = '';
String objectToString = '';
String e = '';
//This variable is creating the problem...
// I have tried this by using a final instead of var, but nothing worked.
var dataAsString = <String>[];
#override
void initState() {
super.initState();
// getUsers();
getUserById();
}
getUserById() {
final String id = itemName;
userRef.doc(id).get().then((DocumentSnapshot doc) {
// final x = doc.data();
// docId= doc.id;
objectToString = doc.data().toString();
String temp = '';
// print(doc.data());
// print(doc.id);
int i = 1;
// int j = 0;
bool end = false;
//We are just parsing the object into string.
while (objectToString[i] != '}') {
if (objectToString[i - 1] == ' ' && objectToString[i - 2] == ':') {
while (objectToString[i] != ',' && end != true) {
// print(z[i]);
temp += objectToString[i];
if (objectToString[i + 1] != '}') {
i++;
} else {
end = true;
}
}
//Here I add all the strings to list...
// This line works fine.
dataAsString.add(temp);
temp = '';
// j++;
print("The code below this line prints everything perfectly");
print(dataAsString.length);
print(dataAsString[0]);
}
i++;
}
// print(dataAsString[0]);
// print(dataAsString[1]);
// print("+++++++++++");
// print(dataAsString[2]);
// for (var k in dataAsString) {
// print(k);
// }
// print(dataAsString);
// setState(() {});
});
}
// getUsers() {
// userRef.get().then((QuerySnapshot snapshot) {
// snapshot.docs.forEach((DocumentSnapshot doc) {
// print(doc.data());
// print(doc.id);
// print(doc.exists);
// });
// });
// }
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: primary_color, title: Text("Apple")),
body: Container(
child: Column(children: [
ListTile(
//The problem arises here and the app do not crash if I run the same code with just a //string in place of dataAsString[0]
title: Text(dataAsString[0]),
),
ListTile(
title: Text(dataAsString[1]),
),
ListTile(
title: Text(dataAsString[2]),
),
]),
),
);
}
}
You cant have data on dataAsString because you are using future(.then) on fetching data. You can do value check like
Text( dataAsString.isNotEmpty? dataAsString[0]: "0 is empty"),
Text( dataAsString.length>2? dataAsString[1]: "1 index is empty"),
Text( dataAsString.length>3? dataAsString[2]: "3rd item is empty"),
It's cause your dataAsString ins't ready on first Flutter rendered frame. So, you need to wait for the getUserById finish to access the dataAsString values.
You can use a builder to check if the data is ready in a readable way.
Builder(
builder: (context) {
if (dataAsString.length >= 2) {
return Column(children: [
ListTile(
title: Text(dataAsString[0]),
),
ListTile(
title: Text(dataAsString[1]),
),
ListTile(
title: Text(dataAsString[2]),
),
]);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
Warning: it'll work cause you're calling setState when you finish the async task.
I would like to be able to retrieve the "CardModele" list.
which is inside the "Cart" class. Please kindly help me.
the responses from the API
{
"MontantTotal": 264775,
"MontantMaxLivraible": 20825,
"qteMax_Livrable": "35",
"prd": "essence",
"id_entite_frs": "TG01-63189572",
"id_entite_conso": "TGO36742859",
"id_souscription": "TG01-63189572TGO367428597586AX",
"CardModele": [
{
"id_model_card": "52893-TG01-63189572",
"name_model_card": "Silver",
"libelle": "Carburant",
"id_opeartion_modCard": "49a813f11634468f3039d79460f27284b48f0d9b"
},
{
"id_model_card": "52893-TG01-63189572",
"name_model_card": "Silver",
"libelle": "Entretien",
"id_opeartion_modCard": "799eec86af09f5015f35663ae4769c0ba3db5467"
}
]
}
My code
import 'dart:convert';
import 'package:argon_flutter/screens/Selling.dart';
import 'package:argon_flutter/screens/carteContent.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:scan/scan.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'Constantes.dart';
import 'login.dart';
class ScanPage extends StatefulWidget {
#override
_ScanPageState createState() => _ScanPageState();
}
class _ScanPageState extends State<ScanPage> {
ScanController Qrscan = ScanController();
SharedPreferences sharedPreferences;
dynamic responserecuID;
String RecupCardId;
String Device;
String Usertoken;
var Idcard ;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
top: true,
bottom: true,
child: Stack(
children: [
ScanView(
controller: Qrscan,
scanAreaScale: .7,
scanLineColor: Colors.green,
onCapture: (data) {
this.Idcard = (data);
print("ID est "+Idcard);
_validator();
// .then((value) {
Qrscan.resume();
// });
},
),
Positioned(
bottom: 0,
left: 0,
child: Row(
children: [
ElevatedButton(
child: Text("Torch"),
onPressed: () {
Qrscan.toggleTorchMode();
},
),
ElevatedButton(
child: Text("pause"),
onPressed: () {
Qrscan.pause();
},
),
ElevatedButton(
child: Text("Scan"),
onPressed: () {
Qrscan.resume();
},
),
],
),
),
],
),
),
);
}
_validator() async {
sharedPreferences = await SharedPreferences.getInstance();
//print("element saisie" + TpeId.text );
sharedPreferences.setString('ScanIDKey',Idcard);
Qrscan.pause();
getValidator();
}
Future getValidator() async {
sharedPreferences = await SharedPreferences.getInstance();
Device = sharedPreferences.getString('valideKey');
Usertoken = sharedPreferences.getString('userid');
await http.get(Uri.parse(Constantes.scannerUrl+
Device+"&id_card="+Idcard
+"&user_token="+Usertoken)).then((response) {
setState(() {
responserecuID = (response.body);
String objText = responserecuID;
Cart reponse = Cart.fromJson(jsonDecode(objText));
print(reponse.my_alert);
sharedPreferences.setString('Qtelvr',reponse.qteMax_Livrable);
sharedPreferences.setInt('Mttlvr',reponse.MontantMaxLivraible);
sharedPreferences.setInt('Mttotal',reponse.MontantTotal);
sharedPreferences.setString('RefPdt',reponse.prd);
sharedPreferences.setString('SousId',reponse.id_souscription);
if(reponse.id_souscription != null && reponse.qteMax_Livrable != null) {
Navigator.of(context).pushAndRemoveUntil(
new MaterialPageRoute(
builder: (BuildContext context) => new carteContent()),
(Route<dynamic> route) => false);
}else {
showDialog(
builder: (context) => new CupertinoAlertDialog(
content: new Text(
reponse.my_alert,
style: new TextStyle(fontSize: 16.0),
),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: new Text("OK"))
],
),
context: context,
barrierDismissible: false);
}
});
});
}
}
class Cart {
int MontantTotal;
int MontantMaxLivraible;
String qteMax_Livrable;
String prd;
String id_entite_frs;
String id_entite_conso;
String id_souscription;
List<CartMod>CardModele;
String my_alert;
String type_alert;
String titre_alert;
Cart(
this.MontantTotal,
this.MontantMaxLivraible,
this.qteMax_Livrable,
this.prd,
this.id_entite_frs,
this.id_entite_conso,
this.id_souscription,
this.CardModele,
this.my_alert,
this.type_alert,
this.titre_alert);
factory Cart.fromJson(dynamic json) {
return Cart(
json['MontantTotal'] as int,
json['MontantMaxLivraible'] as int,
json['qteMax_Livrable'] as String,
json['prd'] as String,
json['id_entite_frs'] as String,
json['id_entite_conso'] as String,
json['id_souscription'] as String,
json['CardModele'] as List ,
json['my_alert'] as String,
json['type_alert'] as String,
json['titre_alert'] as String);
}
#override
String toString() {
return '{ ${this.MontantTotal}, ${this.MontantMaxLivraible}, ${this.qteMax_Livrable}, ${this.prd},${this.id_entite_frs}, ${this.id_entite_conso},${this.id_souscription},${this.CardModele}, ${this.my_alert}, ${this.type_alert}, ${this.titre_alert} }';
}
}
class CartMod{
String id_model_card;
String name_model_card;
String libelle;
String id_opeartion_modCard;
}
I manage to recover the other elements of the answers but I have trouble recovering the list which is inside
The thing is that CardModele is a JSON object and it should be converted from JSON to a CartMod instance. The CartMod class needs then a fromJson constructor the same way the Cart class has one.
The following should do the trick:
class Cart {
int MontantTotal;
int MontantMaxLivraible;
String qteMax_Livrable;
String prd;
String id_entite_frs;
String id_entite_conso;
String id_souscription;
List<CartMod> CardModele;
String my_alert;
String type_alert;
String titre_alert;
Cart(
this.MontantTotal,
this.MontantMaxLivraible,
this.qteMax_Livrable,
this.prd,
this.id_entite_frs,
this.id_entite_conso,
this.id_souscription,
this.CardModele,
this.my_alert,
this.type_alert,
this.titre_alert);
factory Cart.fromJson(dynamic json) {
return Cart(
json['MontantTotal'] as int,
json['MontantMaxLivraible'] as int,
json['qteMax_Livrable'] as String,
json['prd'] as String,
json['id_entite_frs'] as String,
json['id_entite_conso'] as String,
json['id_souscription'] as String,
json['CardModele'] == null
? []
: (json['CardModele'] as List) // <- Here
.map((j) => CartMod.fromJson(j)) // <- Here
.toList(), // <- Here
json['my_alert'] as String,
json['type_alert'] as String,
json['titre_alert'] as String);
}
#override
String toString() {
return '{ ${this.MontantTotal}, ${this.MontantMaxLivraible}, ${this.qteMax_Livrable}, ${this.prd},${this.id_entite_frs}, ${this.id_entite_conso},${this.id_souscription},${this.CardModele}, ${this.my_alert}, ${this.type_alert}, ${this.titre_alert} }';
}
}
class CartMod {
String id_model_card;
String name_model_card;
String libelle;
String id_opeartion_modCard;
CartMod.fromJson(dynamic json) // <- Here
: id_model_card = json['id_model_card'], // <- Here
name_model_card = json['name_model_card'], // <- Here
libelle = json['libelle'], // <- Here
id_opeartion_modCard = json['id_opeartion_modCard']; // <- Here
}
Here CartModele is a list so you have to use
cart.CardModele[0].id_model_card
Here 0 is the index of the element in its list
I'm having a problem when ı try to automatize my Items which is a part of DropDownButton.
Every time ı try to execute the function below ı get this error:The element type 'List<DropdownMenuItem>' can't be assigned to the list type 'DropdownMenuItem'.
I tried not to use map function and did the same as Flutter's official page that describes how to use a dropdown button but nothing has changed. I got the same error.
class DataHelper {
static List<String> tumDerslerinHarflerii() {
return ["AA", "BA", "BB", "CB", "CC", "CD", "DD", "FD", "FF"];
}
static double? harfiNotaCevir(String harf) {
switch (harf) {
case "AA":
return 4;
case "BA":
return 3.5;
case "BB":
return 3.0;
case "CB":
return 2.5;
case "CC":
return 2;
case "DC":
return 1.5;
case "DD":
return 1.0;
case "FD":
return 0.5;
case "FF":
return 0.0;
}
return null;
}
static List<DropdownMenuItem<double>> tumDerslerinHarfleri() {
return tumDerslerinHarflerii()
.map(
(e) => DropdownMenuItem(
child: Text("$e"),
value: harfiNotaCevir(e),
),
)
.toList();
}
}
And I'm using it in my DropDownWidget:
_buildHarfler(GlobalKey buildHarfKey, double _value) {
return Container(
decoration: BoxDecoration(
color: Sabitler.anaRenk.withOpacity(0.3),
borderRadius: Sabitler.borderRadius,
),
child: DropdownButton<double>(
key: buildHarfKey,
value: _value,
items: [
// Dropdown içindeki elementlerin her biri bir widget; liste istiyor.
DataHelper.tumDerslerinHarfleri(),
],
onChanged: (secilenDeger) {
_value = secilenDeger!;
},
),
);
}
change DataHelper.tumDerslerinHarfleri(), to ...DataHelper.tumDerslerinHarfleri(),
this will add the items in the list that are coming from your function (tumDerslerinHarfleri) to the items of your DropdownButton
You need to spread you list. [...DataHelper.tumDerslerinHarfleri()]
I'm using flutter to develop an e-commerce app.
I'm working on the navDrawer for it and I could use some help with the categories.
I have categories that can have subcategories and the subcategories can also have their own subcategories.
Basically, the data set is an array of unknown dimensions.
I need to make a boolean map for my categories and subcategories so that I can keep track of which ones are open in order to show the subcategories.
Here's an example of the dataset:
{
"id":"41490",
"name":"Electrical Equipment",
"subCategories":[
{
"id":"41492",
"name":"Breakers",
"subCategories":[
{
"id":"167542",
"name":"1 Pole",
"subCategories":[
{
"id":"167577",
"name":"15 Amp",
"subCategories":null
},
{
"id":"167585",
"name":"20 Amp",
"subCategories":null
},
{
"id":"167600",
"name":"30 Amp",
"subCategories":null
},
{
"id":"167606",
"name":"40 Amp",
"subCategories":null
}
]
},
I think recursion is the optimal way to process this dataset but the problem I'm having is that I can't figure out how to have dynamic dimensions for an array in Dart.
I already figured out how to generate my listTiles from the dataset but I can't figure out the boolean map.
Is this even possible or should I look into a different approach?
Here's my code for generating the listTiles from the dataset:
void setCategories(List categories){
_categories = categories;
int catCount = categories.length;
_categoryList = new ListView.builder(
//shrinkWrap: true,
//physics: ClampingScrollPhysics(),
padding:EdgeInsets.all(0.0),
itemCount: catCount,
itemBuilder: (BuildContext context, int index) => buildCategories(context, index),
);
}
Widget buildCategories(BuildContext context, int index){
if(_categories[index]['subCategories']!=null){
//TODO: call buildSubCategories with depth of 1 parameter
return Container(
height: 30.0,
child: ListTile(
title: Row(
children:[
Text(" "+_categories[index]['name']),
Transform.scale(
scale: 0.75,
child:
Icon(Icons.arrow_back)
)
]
),
onTap: () {
//TODO: implement boolean map here
}
),
padding: EdgeInsets.all(0.0),
margin: EdgeInsets.all(0.0)
);
} else {
return Container(
height: 30.0,
child: ListTile(
title: Text(" "+_categories[index]['name']),
onTap: () {
}
),
padding: EdgeInsets.all(0.0),
margin: EdgeInsets.all(0.0)
);
}
}
Widget buildSubCategories(var parent, int depth){
List subCategoryList = parent['subCategories'];
int subCategoryCount = subCategoryList.length;
if(parent['subCategories']!=null){
//for each subCategory
//if subCategory has subCategories
//recurse subCategory with depth
buildSubCategories(parent['subCategories'], depth++);
//TODO: implement boolean map here
} else {
//
}
}
void generateCategoryBooleanMap(){
//TODO: generate boolean map here
//TODO: boolean map needs to have a undetermined amount of depth levels
}
Any insight is appreciated even if it means I have to use a different paradigm.
Example of using a Set to keep track of which id is open:
void main() {
final idHandler = IdHandler();
print(idHandler.isIdOpen('MyId')); // false
idHandler.openId('MyId');
print(idHandler.isIdOpen('MyId')); // true
idHandler.closeId('MyId');
print(idHandler.isIdOpen('MyId')); // false
idHandler.openId('MyId');
print(idHandler.isIdOpen('MyId')); // true
idHandler.closeAll();
print(idHandler.isIdOpen('MyId')); // false
}
class IdHandler {
final Set<String> _openIds = {};
void openId(String id) => _openIds.add(id);
void closeId(String id) => _openIds.remove(id);
void closeAll() => _openIds.clear();
bool isIdOpen(String id) => _openIds.contains(id);
}
I would like to know how to implement this code, with three input variables and three different solutions related to each dropdown option. Each time i choose an option, does it block the entry that is not part of the equation and return the calculation value of the selected item?
var _currencies = ['A', 'B', 'C'];
DropdownButtonHideUnderline( child: DropdownButton<String>(
items: _currencies.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value: _currentItemSelected,
isDense: true,
onChanged: (String newValueSelected) {
//code a executar
_onDropDownItemSelected(
newValueSelected);
},
))
String _calculateTotalReturns() {
double entry1 = double.parse(entry1Controller.text);
double entry2 = double.parse(entry2Controller.text);
double entry3 = double.parse(entry3Controller.text);
//Three equations for each dropdown option
double total1 = entry1 * entry2; //FOR DROPDOWN A
double total2 = entry1 + entry2 + entry3 //FOR DROPDOWN B
double total3 = entry1*entry2+entry3 //FOR DROPDOWN C
String result = '';
return result; // How to return result for curerrent dropdown selected when i aply a calculate button???
}
//--------------------------------------------------------------------
child: RaisedButton(
child: Text(
'Calcular',
textScaleFactor: 1.5,
),
color: Theme.of(context).accentColor,
textColor: Theme.of(context).primaryColorDark,
onPressed: () {
setState(() {
if (_formKey.currentState.validate()) {
this.displayResult =
_calculateTotalReturns();
}
});
},
),
You will need to have a global variable which will store the value which value user selected from the dropdown. For example,
String selectedValue; // <-- this will be a global variable.
Change the global variable on onChanged
onChanged: (String newValueSelected) {
selectedValue = newValueSelected;
}
Then you can access this variable in the _calculateTotalReturns() method and return the correct result accordingly like..
String _calculateTotalReturns() {
//other code
String result;
if(selectedValue == 'A'){
result = total1.toString();
}
else if(selectedValue == 'B'){
result = total2.toString();
}
else{
result = total3.toString();
}
return result;
}