uploading images server using graphql apis - flutter-layout

i want to upload my images to the sever from flutter web, which is using graphql api. i am able to show the images on the web but unable to upload images to the server.
static Future<int> multipartApi(File file)async {
print("image_file_path=${file.path}");
var byteData = file.readAsBytesSync();
var multipartFile = MultipartFile.fromBytes(
"",
byteData,
filename: "${DateTime.now().second}.jpeg",
contentType: MediaType("image", "jpeg"),
);
here i am picking images from gallery
final picker = ImagePicker();
List<Uint8List> images = []; // <----change this
List<Uint8List> imageFiles = [];
List<File> imageList = [];
List<int> my_images = [];
pickImage(BuildContext context) async {
List<XFile>? files = await picker.pickMultiImage(imageQuality: 50);
if (files != null) {
for (var element in files) {
imageList.add(File(element.path));
print("imageList= ${imageList.first.path}");
html.File filePath = html.File(element.path.codeUnits, element.path);
print("filePath: ${filePath.toString()}");
imageFiles.add(await element.readAsBytes());
}}
// for (var element in files!) {
// imageList.add(File(element.path));
//
// imageFiles.add(await element.readAsBytes()); // <----change this
// }
print("image path: ${imageList}");
print("Length of images: ${imageList.length}");
setState(() {
images = imageFiles;
print("selected_images: ${images.first.toString()}");
});
print("list length: ${images.length}");
}
and here i am displaying my images inside listview builder.
child: ListView.builder(
itemCount: images.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Image.memory(
images[index],
height: 80,
width: 80,
),
InkWell(
onTap: () {
setState(() {
images.remove(images[index]);
});
},
child: const Icon(Icons.close),
),
],
);
},
),
tell me where i am wrong.

Related

The instance member 'name' can't be accessed in an initializer. Try replacing the reference to the instance member with a different expression [duplicate]

This question already has answers here:
Error: The instance member ... can't be accessed in an initializer
(4 answers)
Closed 4 months ago.
I always get this error when I use the String "name" to locate my Firestore docs. I don't understand why this is happening bc when I use "user.uid" it just works.
The instance member 'name' can't be accessed in an initializer. Try replacing the reference to the instance member with a different expression
This is my code:
final user = FirebaseAuth.instance.currentUser!;
class Folder extends StatelessWidget {
Folder(this.name, {super.key});
final String name;
final Stream<QuerySnapshot> items = FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.collection('Folder')
.doc(name)
.collection('Items')
.snapshots();
#override
Widget build(BuildContext context) {
return Column(
children: [
// Title
Text(name, style: Theme.of(context).textTheme.headlineSmall),
// List with Items
StreamBuilder(
stream: items,
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
final data = snapshot.requireData;
if (snapshot.hasData) {
return ListView.builder(
itemCount: data.size,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return ListTile(
title: Text(data.docs[index]['name']),
onTap: () {},
);
},
);
}
if (snapshot.hasError) {
return const Text("error");
}
return const Text("error");
},
),
],
);
}
}
And I pass the String from this StreamBuilder:
stream: folder,
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
final data = snapshot.requireData;
if (snapshot.hasError) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(00.0),
child: ListView.builder(
padding: const EdgeInsets.only(bottom: 100, top: 20),
itemCount: data.size,
itemBuilder: (context, index) {
return Folder(
data.docs[index]["name"].toString()
);
},
),
);
}
return const Center(child: CircularProgressIndicator());
},
),
You could just add a late modifier to the items variable. Like this:
late final Stream<QuerySnapshot> items = FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.collection('Folder')
.doc(name)
.collection('Items')
.snapshots();
To explain why this works: basically you can't use any instance variables when initializing other instance variables because they are all initialized when the class gets instantiated. When you add the late modifier, the variable will only be initialized when it's first used, meaning all the non-late variables will already be initialized.

How to view json List of Map data in ListView builder

"images":[
{
"id":11,
"imageName":"xCh-rhy"
},
{
"id":31,
"imageName":"fjs-eun"
} ];
Try this,
Create model,
class Image {
final String id;
final String name;
Images({this.id, this.name});
}
Parse & Add Data,
List<Image> parsedImages = [];
List<dynamic> jsonImages = jsonData["images"];
jsonImages.forEach(
(imgInfo) {
parsedImages.add(
Image(
id: imgInfo["id"],
name: imgInfo["imageName"],
)
);
}
);
Build List,
ListView.builder(
itemBuilder: (context, index) {
return ListTile(title: Text(parsedImages.name));
},
itemCount: parsedImages.length,
)

I am sending the GET request to the flutter app from the express API but I am not getting any output

I am sending the GET request to the flutter app from the express API but I am not getting any output in the flutter App. The API is working in the postman and I am getting the perfect output in the postman.
Please help
testing() async{
debugPrint("Hello");
http.Response response = await
http.get("http://192.168.119.97:3000/api/cricketer");
debugPrint((response.body));
debugPrint("Hello hy");
}
Future getData() async {
http.Response response = await
http.get("http://192.168.119.97:3000/api/cricketer");
debugPrint((response.body));
data = json.decode(response.body);
debugPrint(('$data'));
setState(() {
userData = data["cricketers"];
debugPrint("Hello ");
debugPrint(('$userData'));
});
}
Calling the Function:
#override
void initState() {
super.initState();
getData();
testing();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Cricketer Info"),
backgroundColor: Colors.pink,
),
body: ListView.builder(
itemCount: userData == null ? 0 : userData.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
children: <Widget>[
// CircleAvatar(
// backgroundImage: NetworkImage(userData[index][""]),
// ),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text("${userData[index]["name"]}",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w700,
),),
)
],
),
),
);
},
),
);
}
}
I have uploaded the code also. Please check and if possible help
First, you have to JSON decode the body for print, json.decode() gives some misleading. You can use jsonDecode(result.body) from 'dart:convert' package . Here I have attached some
example codes of login(Post request). After decoding you can use a data model and factory method to convert to a dart object.
repo dart file that send post request
my data model with a factory method for decode json to dart

(Flutter) How can I identify which ListTile in my ListView the user clicked the PopupMenuItem?

I have a ListView which holds ListTiles. Each tile represents a user of my users array. The trailing of a tile is a PopupMenuButton. When the user clicks on one PopupMenuItem, a function shall be called. So far so good. In the "onSelected" I would like to pass data of the corresponding user to a function.
Could anybody please give me a hint, how I should change the code to be able to do so?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:flutter/material.dart';
class UserListMobilePortrait extends StatelessWidget {
final List<QueryDocumentSnapshot> users;
const UserListMobilePortrait({
Key key,
this.users,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final HttpsCallable setRoleCallable = CloudFunctions.instance
.getHttpsCallable(functionName: 'setRoles')
..timeout = const Duration(seconds: 10);
final button = new PopupMenuButton(
itemBuilder: (_) => <PopupMenuItem<String>>[
new PopupMenuItem<String>(
child: const Text('Make Admin'), value: 'admin'),
new PopupMenuItem<String>(
child: const Text('Make Editor'), value: 'editor'),
],
onSelected: (selectedItem) async {
try {
final HttpsCallableResult result = await setRoleCallable.call(
<String, dynamic>{
//'user' shall represent the user of the clicked ListTile, but how to pass it?
'email': user.data()['email'],
'role': selectedItem,
'permission': 'grant'
},
);
print(result.data);
} on CloudFunctionsException catch (e) {
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
} catch (e) {
print('caught generic exception');
print(e);
}
});
return ListView(
children: users
.map((user) => ListTile(
title: Text(
(user.data()['email'] != null) ? user.data()['email'] : ""),
subtitle: Row(
children: [
Text((user.data()['displayName'] != null)
? user.data()['displayName']
: ""),
Container(
width: 6,
),
user.data()['isAdmin'] == true
? Chip(
label: Text('admin'),
backgroundColor: Colors.orange[600],
shadowColor: Colors.orange[900],
)
: Text(''),
Container(
width: 6,
),
user.data()['isEditor'] == true
? Chip(
label: Text('editor'),
backgroundColor: Colors.blue[600],
shadowColor: Colors.blue[900],
)
: Text(''),
],
),
trailing: button,
))
.toList(),
);
}
}
understanding your problem a simple workaround will be to use a Listview Builder(And also using a ListView Builder will optmize the app for speed)
const List = ["Hello", "World", "Temp"]
ListView.builder(
itemBuilder: (context, index) {
//return (Your widget [a list tile preferably and use onTap(and access the index
in the function)])
return(ListTile(onTap:(){
print(List[index]);
//you can access the index and use the main list to get its following data
};
};
This will workout :)
My solution was moving the former final button to its own class. So I can pass the data to the constructor.
UserPopupMenuButton
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:flutter/material.dart';
class UserPopupMenuButton extends StatelessWidget {
final QueryDocumentSnapshot user;
const UserPopupMenuButton({
Key key,
this.user,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final HttpsCallable setRoleCallable = CloudFunctions.instance
.getHttpsCallable(functionName: 'setRoles')
..timeout = const Duration(seconds: 10);
return PopupMenuButton(
itemBuilder: (_) => <PopupMenuItem<String>>[
new PopupMenuItem<String>(
child: const Text('Make Admin'), value: 'admin'),
new PopupMenuItem<String>(
child: const Text('Make Editor'), value: 'editor'),
],
onSelected: (selectedItem) async {
try {
final HttpsCallableResult result = await setRoleCallable.call(
<String, dynamic>{
'email': user.data()['email'],
'role': selectedItem,
'permission': 'grant'
},
);
print(result.data);
} on CloudFunctionsException catch (e) {
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
} catch (e) {
print('caught generic exception');
print(e);
}
});
}
}
And using it as the trailing for the ListTile:
trailing: UserPopupMenuButton(user: user),

How to get the file selected

I am building a flutter web using old version. I am having a FileUploadInputElement. I need to get the file selected from that element.
#override
Widget build(BuildContext context) {
FileUploadInputElement fileUploadInputElement = FileUploadInputElement();
ui.platformViewRegistry.registerViewFactory(
'animation-Image-html', (int viewId) => fileUploadInputElement);
return SizedBox(
child: HtmlElementView(
viewType: 'animation-Image-html',
),
);
}
You can directly use the element.files property to access the files and use the Filreader class from dart:html. I have created an example below to show you how a text file and image can be read. This example is based on FileReader examples in another post.
Accessing the file
Here element is the FileUploadInputElement reference.
element.files[0] or in case of multiple files element.files
Set up your file reader
String option1Text = "Initialized text option1";
Uint8List uploadedImage;
FileUploadInputElement element = FileUploadInputElement()..id = "file_input";
// setup File Reader
FileReader fileReader = FileReader();
Use FileReader to read the file
fileReader.readAsText(element.files[0])
connect the listener for load event
fileReader.onLoad.listen((data) {
setState(() {
option1Text = fileReader.result;
});
});
connect error events
fileReader.onError.listen((fileEvent) {
setState(() {
option1Text = "Some Error occured while reading the file";
});
});
Use Image.memory to show images from byte array.
Image.memory(uploadedImage)
Note: In the following example we choose a file and click the respective button to handle the file reading. But the same can be achieved by connecting the logic in respective events of the FileUploadInputElement element in a similar approach. eg: element.onLoad.listen or element.onError.listen event streams.
Full Example
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:html';
class FileUploadTester extends StatefulWidget {
#override
_FileUploadTesterState createState() => _FileUploadTesterState();
}
class _FileUploadTesterState extends State<FileUploadTester> {
String option1Text = "Initialized text option1";
Uint8List uploadedImage;
FileUploadInputElement element = FileUploadInputElement()..id = "file_input";
// setup File Reader
FileReader fileReader = FileReader();
// reader.onerror = (evt) => print("error ${reader.error.code}");
#override
Widget build(BuildContext context) {
ui.platformViewRegistry.registerViewFactory("add_input", (int viewId) {
return element;
});
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
FlatButton(
color: Colors.indigoAccent,
child: Text('ReadFile'),
onPressed: () {
fileReader.onLoad.listen((data) {
setState(() {
option1Text = fileReader.result;
});
});
fileReader.onError.listen((fileEvent) {
setState(() {
option1Text = "Some Error occured while reading the file";
});
});
fileReader.readAsText(element.files[0]);
},
),
Expanded(
child: Container(
child: Text(option1Text),
),
),
Expanded(child: HtmlElementView(viewType: 'add_input')),
Expanded(
child: uploadedImage == null
? Container(
child: Text('Uploaded image should shwo here.'),
)
: Container(
child: Image.memory(uploadedImage),
),
),
FlatButton(
child: Text('Show Image'),
color: Colors.tealAccent,
onPressed: () {
fileReader.onLoad.listen((data) {
setState(() {
uploadedImage = fileReader.result;
});
});
fileReader.onError.listen((fileEvent) {
setState(() {
option1Text = "Some Error occured while reading the file";
});
});
fileReader.readAsArrayBuffer(element.files[0]);
},
),
],
);
}
}
Below
Image Upload in Flutter Web - Working perfectly fine for me :)
startFilePicker() async {
FileUploadInputElement uploadInput = FileUploadInputElement();
uploadInput.multiple = true;
uploadInput.draggable = true;
uploadInput.click();
uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
print(files);
if (files != null && files.isNotEmpty) {
for (var i = 0; i < files.length; i++) {
FileReader reader = FileReader();
reader.onLoadEnd.listen((e) async {
if (reader.result != null) {
Uint8List? _byteData = reader.result as Uint8List;
// upload the image
}
});
reader.onError.listen((fileEvent) {
Fluttertoast.showToast(
msg: "Some Error occured while reading the file");
});
reader.readAsArrayBuffer(files[i]);
}
} else {
Fluttertoast.showToast(msg: 'Images not selected');
}
});
}

Resources