How to create dynamic forms in flutter with FutureBuilder - flutter

I want to create dynamic forms and fetch data after submitted form. I have an API and I'm getting questions from this API. In application, user will answer questions and save the result to API. How can I create dynamic forms and retrieve user inputs. Please help.
FutureBuilder<List<ConditionType>>(
future: _api.getConditionTypes(job.sectorId),
builder: (context, snapshot) {
//Create Form
}

Try using json_to_form, If you could share the structure of the response I could assist to tweaking the plugin which I had to do for my own project. I should mention that with this implementation DropDownButton tends to have issues displaying values though it saves them.

I make the Json tranforms making the model of the object and then make the request:
class Model {
String projectName;
String datePlan;
String activityName;
String hours;
TimeSheetModel({this.projectName, this.datePlan, this.activityName, this.hours});
TimeSheetModel.fromJson(Map<String, dynamic> json){
projectName = json["ProjectName"];
datePlan = json["DatePlan"];
activityName = json["ActivityName"];
hours = json["Hours"];
}
Map toMap() {
var map = new Map<String, dynamic>();
map["ProjectName"] = projectName;
map["DatePlan"] = datePlan;
map["ActivityName"] = activityName;
map["Hours"] = hours;
return map;
}
}
The method fromJson transforms Json data to your object for GET request and toMap tranform your object to Json for POST or PUT request.
Making the GET request:
getProjects() async {
var url = 'url';
var res = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json",
"charset": "UTF-8"});
data = json.decode(res.body);
setState(() {
Model data = Model.fromJson(resBody);
});
}
Making the POST request:
post() async {
var url = 'url';
http.post(url, body:
data.toMap()).then((response) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
});
}

Related

How to make a http post using form data in flutter

I'm trying to do a http post request and I need to specify the body as form-data, because the server don't take the request as raw or params.
here is the code I tried
** Future getApiResponse(url) async {
try {
// fetching data from the url
final response = await http.get(Uri.parse(url));
// checking status codes.
if (response.statusCode == 200 || response.statusCode == 201) {
responseJson = jsonDecode(response.body);
// log('$responseJson');
}
// debugPrint(response.body.toString());
} on SocketException {
throw FetchDataException(message: 'No internet connection');
}
return responseJson;
}
}
but its not working. here is the post man request
enter image description here
its not working on parms. only in body. its because this is in form data I guess.
how do I call form data in flutter using HTTP post?
First of all you can't send request body with GET request (you have to use POST/PUT etc.) and you can use Map for request body as form data because body in http package only has 3 types: String, List or Map. Try like this:
var formDataMap = Map<String, dynamic>();
formDataMap['username'] = 'username';
formDataMap['password'] = 'password';
final response = await http.post(
Uri.parse('http/url/of/your/api'),
body: formDataMap,
);
log(response.body);
For HTTP you can try this way
final uri = 'yourURL';
var map = new Map<String, dynamic>();
map['device-type'] = 'Android';
map['username'] = 'John';
map['password'] = '123456';
http.Response response = await http.post(
uri,
body: map,
);
I have use dio: ^4.0.6 to create FormData and API Calling.
//Create Formdata
formData = FormData.fromMap({
"username" : "John",
"password" : "123456",
"device-type" : "Android"
});
//API Call
final response = await (_dio.post(
yourURL,
data: formData,
cancelToken: cancelToken ?? _cancelToken,
options: options,
))

convert JSON from google app script to flutter

i'm trying to fetch data from a range of two columns on google sheet
first column with numbers,second column text
to my flutter app.
i managed to make the the http request
by this line of code:
var url = Uri.parse(
'https:`enter code here`//script.googleusercontent.com/macros/echo?user_content_key=Bzv-qcg70rUkHCr4pjI_k_qlB9c5I_GjKS-U726WCslGZ0tulYSbfdD1DabRoVrrbDSn9rIS78vQxr33OOOjaAw4d4DcA8sGm5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnBqJjZp2jp3I5Qlxq6dcbGTdqr4FTByb3YAAvkZxH-A03NfLQ3Ce8hucRs86AXu4Vcg63MBXANpH4BVmytCxmg24Mg9dF6sKjQ&lib=M7v_2CxFrrqdcmzthOkMrc1jilJU4QU4H');
void getData() async {
Response response = await get(url);
if(response.statusCode == 200) {}
var feedback = convert.jsonDecode(response.body);
print('Response body: ${response.body}');
}
when i'm printing the response body,i'm getting the whole data
now,what i'm trying to do is to enter a number to a TextField in the flutter app
and to get a result from the parallel second column next to the first column where is typed the number i entered.
=============================
update
i've created a model from my json data
this the model created from the website
https://javiercbk.github.io/json_to_dart/
class Note {
late String id;
Note({required this.id});
Note.fromJson(Map<String, dynamic> json) {
id = json['id'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
return data;
}
}
now this the new code for getting the data from google sheet
Future<void> getData() async {
var response = await http.get(Uri.parse(
"https://script.google.com/macros/s/AKfycbzU89ZEE0Y9sgEQZMZHSbX00M6hPdHOX6WN8IjQWa5lzgAzmAc4jZShpUfKbnJ5zm8J/exec"));
var body = response.body;
Note note = Note.fromJson(jsonDecode(body));
print(note.id.toString());
}
and i'm getting an error when trying to run the flutter app on vscode
a new tab of browser client opened no data come from the google sheet api
and this a screenshot from the vscode
While working with JSON data
The good practice is to create a model for that and then just fetch the data through the API
creating a model and a class is easy enough and doesn't take effort and makes your work easy ;)
For creating a model for your project
VISIT https://javiercbk.github.io/json_to_dart
Just copy your JSON data and paste in the textField and you will get your Model Class ready with just one click
for accessing the data
Test _test = Test.fromJson(response.body);
that's it.
refer image shown below

Flutter: trying to use jsonDecode - Error: string is not a subtype of type int of index Error

I want to use CoinMarketCap API in flutter. But where I want to add data from map to list, an error will occur which says:
type 'string' is not a subtype of type 'int' of 'index'.
here's my code, I used this tutorial Migrating to the new CoinMarketCap API with Flutter
Future<void> getCryptoPrices() async{
List cryptoDatas = [];
print('Crypto Prices are Loading...');
String apiURL= "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest";
http.Response response = await http.get(apiURL, headers: {'X-CMC_PRO_API_KEY': 'api code'});
Map<String, dynamic> responseJSON = json.decode(response.body);
if (responseJSON["status"]["error_code"] == 0) {
for (int i = 1; i <= responseJSON["data"].length; i++) {
cryptoDatas.add(responseJSON["data"][i.toString()]); // THE ERROR WILL HAPPEND HERE
}
}
setState(() {
this.cryptoList = cryptoDatas;
print(cryptoList);
});
Thank you in advance.
I had this same problem today, and I fixed it with this code. The code is a little different from yours but should do the same thing. If it didn't work then let me know.
Future<String> getCryptoPrices() async {
// API URL
var response = await http.get(
Uri.parse("API URL"),
// Only Accepts data in the formate of json
headers: {
"Accept": "application/json",
});
// this gets the data from the json
var first = json.decode(response.body);
//this is optional if you want to filter through the data
var second = first['current'];
var third = second['temp'];
// this prints out the data from the json
setState(() {
print(third);
});
}
change this line
cryptoDatas.add(responseJSON["data"][i.toString()])
to:
cryptoDatas.add(responseJSON["data"][i])

How to send json object with http post multipart request in Flutter

I have to send a multipart HTTP post request that contains a image, body and header, Please find the body format
body: {
"Id":Id,
"Details": {
"name": Name,
"centroid": centroid,
"attribute": {
"boundaryOpacity": boundaryOpacity,
"boundaryWeight": boundaryWeight,
"boundaryColor": boundaryColor,
"labelColor": labelColor,
},
},}
headers: {
'tenantId': tenantId,
'Content-Type': 'multipart/form-data',
'x-access-token': token
},
I have to send image along with this request .Please help me with this.
You can convert your map into multipartRequest and set your headers in multipartRequest.
Future<void> addProject(Project project, [File? file]) async {
final url = Uri.parse('$baseUrl/api/projects');
final format = DateFormat('yyyy-MM-dd');
final completionDate = format.format(project.completionDate);
final data = {
'id': project.id,
'title': project.title,
'description': project.description,
'image': project.image,
'completion_date': completionDate,
};
try {
var request = http.MultipartRequest('POST', url);
request = jsonToFormData(request, data);
request.headers['X-Requested-With'] = "XMLHttpRequest";
request.headers['Authorization'] = "Bearer $authToken";
if (file != null) {
request.files
.add(await http.MultipartFile.fromPath("image", file.path));
}
final response = await request.send();
final responseData = await response.stream.toBytes();
final responseString = String.fromCharCodes(responseData);
print(responseString)
notifyListeners();
} catch (error) {
print('Error add project $error');
throw (error);
}
}
jsonToFormData(http.MultipartRequest request, Map<String, dynamic> data) {
for (var key in data.keys) {
request.fields[key] = data[key].toString();
}
return request;
}
You can't send json encoded string with multipart, you have to do it formdata way, you may need to update your backend code
final req = http.MultipartRequest('POST', url);
// Write your add files statement here
req.fields['id'] = id; // This is your id field
req.fields['details[name]'] = Name; // This is name field in details object
req.fields['details[attribute][boundaryOpacity]'] = boundaryOpacity; // This is how you write nested fields
You can follow same pattern for other fields as well, you need to implment a check for null field, assuming id can be null, write it as follows
req.fields['id'] = id != null ? id : ''; // If it is null convert it to empty string or don't include it
Alternate solution
Add a data field and convert entire payload to json string and decode at backend.

Incomplete response JSON body with flutter http.Request.send()

I am not sure what is going on with my function. I am trying to have a generic request function that I can use with any request method (GET, POST, etc...). Everything is working well, except for the POST response, it is missing data. I double checked what is expected to be returned and compared it with the response from Postman and my code. My code produces less data than expected and Postman.
Here is what I am doing
class HttpClientHandler {
String baseUrl = 'jsonplaceholder.typicode.com';
String path = '/posts';
static const Map<String, String> defaultHeaders = {'': ''};
static const Map<String, String> defaultBody = {'': ''};
Future<dynamic> request(HttpMethod method,
{Map<String, String> headers = defaultHeaders,
Map<String, dynamic> body}) async {
var uri = Uri.https(baseUrl, '$path');
var request = http.Request(method.type, uri);
request.headers.addAll(headers);
request.body = body.toString();
var response = await request.send();
if (response.statusCode >= 200 && response.statusCode <= 299) {
String rawData = await response.stream.transform(utf8.decoder).join();
return jsonDecode(rawData);
} else {
throw Exception();
}
}
}
The caller simply does the following:
var _client = HttpClientHandler();
var data = await _client.request(HttpMethod.POST, body: {'title': 'foo', 'body': 'bar', 'userId': 1});
print(data);
The response I get is:
{id: 101}
The expected response is:
{
"title": "foo",
"body": "bar",
"userId": "1",
"id": 101
}
I am using import 'package:http/http.dart' as http; package. Is this a stream, transform, or headers issue?
I found what was wrong in my implementation, I didn't jsonEncode my request body. The test API I am using here replies the same request body it receives. Since I wasn't encoding the body correctly, it only was recognizing the first data being sent.
So, the fix is to change this line:
request.body = body.toString();
to this line:
request.body = jsonEncode(body);
Also, I ended up parsing the stream byte to string differently, from:
String rawData = await response.stream.transform(utf8.decoder).join();
To:
String rawData = await response.stream.bytesToString();