setState not updating when passing variable to function in Flutter - flutter

when I pass the variables to a function that has a setState method, it does not update, when I call the variable directly from the same function it works fine, I'm not sure what I am doing wrong here:
code:
_startFilePicker(Uint8List chosenFile, var color, IconData iconData) async {
InputElement uploadInput = FileUploadInputElement();
uploadInput.click();
uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
if (files.length == 1) {
final file = files[0];
FileReader reader = FileReader();
reader.onLoadEnd.listen((e) {
setState(() {
print("on load set state");
chosenFile = reader.result;
iconData = Icons.done;
color = Colors.green[500];
});
});
reader.onError.listen((fileEvent) {
setState(() {
print("error");
//"Some Error occured while reading the file";
});
});
reader.readAsArrayBuffer(file);
}
});
}
when I call the _startFilePicker(attachmentOne, firstAttachmentColor, firstAttachment) the variables are not updated in the setState method called in function, however when I call those variables directly inside the function like so:
reader.onLoadEnd.listen((e) {
setState(() {
print("on load set state");
attachmentOne = reader.result;
firstAttachment = Icons.done;
firstAttachmentColor = Colors.green[500];
});
});
The button that is calling this function:
ElevatedButton(
child: Icon(iconda),
onPressed: () => setState(() {
_startFilePicker(chosenfile, color, iconda);
}),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(color),
),
),
Any insight would be much appreciated.
Note: all code and variables are in the same class state.
Thanks,

Try this.
_startFilePicker(Uint8List chosenFile, var color, IconData iconData) async {
InputElement uploadInput = FileUploadInputElement();
uploadInput.click();
uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
if (files.length == 1) {
final file = files[0];
FileReader reader = FileReader();
reader.onLoadEnd.listen((e) {
print("on load set state");
chosenFile = reader.result;
iconData = Icons.done;
color = Colors.green[500];
setState((){});
});
reader.onError.listen((fileEvent) {
print("error");
//"Some Error occured while reading the file";
});
reader.readAsArrayBuffer(file);
}
});

_startFilePicker() async {
InputElement uploadInput = FileUploadInputElement();
uploadInput.click();
uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
if (files.length == 1) {
final file = files[0];
FileReader reader = FileReader();
reader.onLoadEnd.listen((e) {
print("on load set state");
return [reader.result,Icons.done,Colors.green[500]];
});
reader.onError.listen((fileEvent) {
print("error"); //"Some Error occured while reading the file";
});
reader.readAsArrayBuffer(file);
}});
}
// then pass your value like this...
renderr() async {
attachmentOne = _startFilePicker()[0];
firstAttachment = _startFilePicker()[1];
firstAttachmentColor = _startFilePicker()[2];
setState() {};
}
just call renderr();
This should give you an idea

Related

How to Read a docx file text from google drive?

Future<void> _loadFileContent() async {
final file = File(widget.filePath);
final extension = file.path.split('.').last.toLowerCase();
if (extension == 'pdf') {
final pdf = await PDFDoc.fromFile(file);
final pages = await pdf.pages;
final texts = await Future.wait(pages.map((page) => page.text));
_fileContent = texts.join('\n');
} else if (extension == 'txt') {
_fileContent = await file.readAsString();
// var decoded = base64.decode( _fileContent);
} else if (extension == 'docx') {
} else {
throw Exception('Unsupported file extension: $extension');
}
setState(() {
_isLoading = false;
});
How to Read a docx file text from google drive? How to implement with use of libary any suggection

Turning String into File or vice versa in Flutter

I have a little question I have been banging my head on for a few days.
void _loadImage() async {
SharedPreferences saveImage = await SharedPreferences.getInstance();
setState(() {
if (_imagepath == null) {
_imagepath = MemoryImage(kTransparentImage);
}else{
_imagepath = saveImage.getString('imagepath');
}
});
}
So I have this function to save the image to shared preferences, but would like for if else check before it executes that if the path (which is a string) is null, it turns to transparent, and if not, to just regular path. This syntax obviously doesn't work since the String doesn't equal to File:
_imagepath = MemoryImage(kTransparentImage);
Where the _imagepath is a String (a path) and the MemoryImage is a File.
Is there a simple solution to make this work within a function?
If you have to do it in this function then you can do it like this:
ImageProvider _image;
void _loadImage() async {
SharedPreferences saveImage = await SharedPreferences.getInstance();
setState(() {
if (_image == null) {
_image = MemoryImage(kTransparentImage);
} else {
var path = saveImage.getString('imagepath');
var file = File(path);
_image = FileImage(file);
}
});
}
#override
Widget build(BuildContext context) {
return Image(image: _image);
}

How to listen("close" event) to the file download window in flutter web?

My code allows to open the file upload window using universal_html.InputElement uploadInput = universal_html.FileUploadInputElement(); web Flutter and select the necessary files to load them into the project. If the user does not select any photo and clicks on close/cancel the window, I want react to this. How can i understand that user close window?
final completer = Completer<List<String>>();
universal_html.InputElement uploadInput = universal_html.FileUploadInputElement();
uploadInput.multiple = true;
uploadInput.accept = 'image/*';
uploadInput.click();
uploadInput.addEventListener('change', (e) async {
final files = uploadInput.files;
Iterable<Future<String>> resultsFutures = files.map((file) {
final reader = universal_html.FileReader();
reader.readAsDataUrl(file);
reader.onError.listen((error) => completer.completeError(error));
return reader.onLoad.first.then((_) => reader.result as String);
});
final results = await Future.wait(resultsFutures);
completer.complete(results);
});
universal_html.document.body.append(uploadInput);
final List<String> images = await completer.future;
uploadInput.remove();
A way to manage this kind of event is used in the web implementation of the package file_picker.
Here is a code sample to help you (you can also find the full implementation from the package here):
import 'dart:html' as html;
import 'dart:async';
Future<html.File?> pickFile(String type) async {
final completer = Completer<List<html.File>?>();
final input = html.FileUploadInputElement() as html.InputElement;
input.accept = '$type/*';
var changeEventTriggered = false;
void changeEventListener(html.Event e) {
if (changeEventTriggered) return;
changeEventTriggered = true;
final files = input.files!;
final resultFuture = files.map<Future<html.File>>((file) async {
final reader = html.FileReader();
reader.readAsDataUrl(file);
reader.onError.listen(completer.completeError);
return file;
});
Future.wait(resultFuture).then((results) => completer.complete(results));
}
void cancelledEventListener(html.Event e) {
html.window.removeEventListener('focus', cancelledEventListener);
// This listener is called before the input changed event,
// and the `uploadInput.files` value is still null
// Wait for results from js to dart
Future.delayed(Duration(milliseconds: 500)).then((value) {
if (!changeEventTriggered) {
changeEventTriggered = true;
completer.complete(null);
}
});
}
input.onChange.listen(changeEventListener);
input.addEventListener('change', changeEventListener);
// Listen focus event for cancelled
html.window.addEventListener('focus', cancelledEventListener);
input.click();
final results = await completer.future;
if (results == null || results.isEmpty) return null;
return results.first;
}
The idea is to rely on a listener on the focus event so when you will lose the focus on your file picker window without any data loaded it will complete your future with a null value.

How to return in to parent's scope from inline function?

So pickFromFile is a Future, which returns after some time. In reader.onLoadEnd I'm trying to return, but how can I return to pickFromFile's scope, instead of returning in the scope of inline function, that is given as an argument to onLoadEnd.listen?
Future<ByteData> pickFromFile() async
{
InputElement uploadInput = FileUploadInputElement();
uploadInput.multiple = false;
uploadInput.accept = 'image/*';
uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
if (files.length == 1) {
final file = files[0];
final reader = FileReader();
reader.onLoadEnd.listen((e) {
var result = reader.result;
var base64 = result.toString().split(",")[1];
var bytes = base64Decode(base64);
return ByteData.view(bytes.buffer);
});
reader.readAsDataUrl(file);
}
});
uploadInput.click();
}
I have a then listener on pickFromFile which does not get called in case I return like in the example above.
Found an answer myself. Completer is what I was looking for.
Future<List<Base>> GetItemList(){
var completer = new Completer<List<Base>>();
// At some time you need to complete the future:
completer.complete(new List<Base>());
return completer.future;
}

Flutter web upload file

I want to upload files using Flutter web, but I encountered some problems, my steps are as follows:
/// choose file
void _chooseFile() {
InputElement uploadInput = FileUploadInputElement();
uploadInput.accept = ".mp4";
uploadInput.multiple = true;
uploadInput.click();
uploadInput.onChange.listen((event) {
final files = uploadInput.files;
if (files.length == 1) {
final file = files[0];
final reader = FileReader();
reader.onLoadEnd.listen((event) {
print('loaded: ${file.name}');
print('type: ${reader.result.runtimeType}');
print('file size = ${file.size}');
_uploadFile(file);
});
reader.onError.listen((event) {
print(event);
});
reader.readAsArrayBuffer(file);
}
});
}
/// upload file
/// file: in dart:html package not in dart:io package
void _uploadFile(File file) async {
FormData data = FormData.fromMap({
'file': MultipartFile.fromBytes(
List<int>, // -----------------------------> problem line
filename: file.name,
)
});
Dio dio = new Dio();
dio.post('upload file url', data: data, onSendProgress: (count, total) {
print('$count ==> $total');
}).then((value) {
print('$value');
}).catchError((error) => print('$error'));
}
The problem is that MultipartFile.fromBytes(List<int> value, {...}), but I don't know how to conver file ( in dart:html not in dart:io ) to List<int>.
Thanks!!!
You need to convert the reader, as below:
List<int> _selectedFile;
Uint8List _bytesData;
void _handleResult(Object result) {
setState(() {
_bytesData = Base64Decoder().convert(result.toString().split(",").last);
_selectedFile = _bytesData;
});
}
call the func:
_handleResult(reader.result);
then, pass _bytesData to your MultipartFile.fromBytes(...) or have return func type as List<int> and call it anywhere you need.
For example, this is what I have done to get the image:
List<int> imageFileBytes;
/// Browse Image:
_setImage(int index) async {
html.InputElement uploadInput = html.FileUploadInputElement();
uploadInput.multiple = false;
uploadInput.draggable = true;
uploadInput.accept = 'image/*';
uploadInput.click();
html.document.body.append(uploadInput);
uploadInput.onChange.listen((e) {
final files = uploadInput.files;
final file = files[0];
final reader = new html.FileReader();
reader.onLoadEnd.listen((e) {
var _bytesData = Base64Decoder().convert(reader.result.toString().split(",").last);
setState(() {
imageFileBytes = _bytesData;
});
});
reader.readAsDataUrl(file);
});
uploadInput.remove();
}
InputElement uploadInput = FileUploadInputElement();
uploadInput.accept = 'image/*';
uploadInput.click();
uploadInput.onChange.listen(
(changeEvent) {
final file = uploadInput.files.first;
final reader = FileReader();
reader.readAsDataUrl(file);
reader.onLoadEnd.listen(
(loadEndEvent) async {
_file = file;
setState(() {});
},
);
},
);
That code Work fine for me.