How to handle complex API data response in Flutter GetX using observable method
item_model.dart
class ItemModel {
int id;
String description;
String amount;
String type;
int userId;
DateTime createdAt;
DateTime updatedAt;
ItemModel.fromJson(Map<String, dynamic> data) {
id = data['id'];
description = data['description'];
amount = data['amount'];
type = data['type'];
userId = data['userId'];
if (data['created_at'] != null) createdAt = DateTime.parse(data['created_at']);
if (data['updated_at'] != null) updatedAt = DateTime.parse(data['updated_at']);
}
}
page_links_model.dart
class PageLinksModel {
String first, last, prev, next;
PageLinksModel.fromJson(Map<String, dynamic> data) {
first = data['first'];
last = data['last'];
prev = data['prev'];
next = data['next'];
}
}
pages_status_model.dart
class PagesStatusModel {
int currentPage, from, lastPage;
var links = List<PageInfoModel>();
String path;
int perPage, to, total;
PagesStatusModel.fromJson(Map<String, dynamic> data) {
currentPage = data['current_page'];
from = data['from'];
lastPage = data['last_page'];
(data['links'] as List).forEach((e) => links.add(PageInfoModel.fromJson(e)));
path = data['path'];
perPage = data['per_page'];
to = data['to'];
total = data['total'];
}
}
class PageInfoModel {
String url;
dynamic label;
bool active;
PageInfoModel.fromJson(Map<String, dynamic> data) {
url = data['url'];
label = data['label'];
active = data['active'];
}
}
transaction_model.dart
import 'package:getx_api/models/pages_status_model.dart';
class TransactionModel {
var data = List<ItemModel>();
PageLinksModel links;
PagesStatusModel meta;
TransactionModel.fromJson(Map<String, dynamic> source) {
(source['data'] as List).forEach((e) => data.add(ItemModel.fromJson(e)));
links = PageLinksModel.fromJson(source['links']);
meta = PagesStatusModel.fromJson(source['meta']);
}
}
net_service.dart
import 'dart:convert';
import 'package:getx_api/src/shared/transactions_data.dart';
import 'package:http/http.dart' as http;
class NetService {
static Future fetchJsonData(String url) {
return
http.get(url)
.then((response) => response?.statusCode == 200 ? jsonDecode(response.body) : null)
.catchError((err) => print(err));
}
static Future fetchLocalJsonData() async {
await Future.delayed(Duration(seconds: 3));
return jsonDecode(transactionData) as Map<String, dynamic>;
}
}
transaction_controller.dart
import 'package:get/get.dart';
import 'package:getx_api/models/transaction_model.dart';
import 'package:getx_api/services/net_service.dart';
const _serverUrl = 'http://10.0.2.2:8000/api/transactions';
class TransactionController extends GetxController {
var _trx;
var _dataAvailable = false.obs;
@override
void onInit() {
super.onInit();
fetchTransactions();
}
bool get dataAvailable => _dataAvailable.value;
TransactionModel get trx => _trx;
Future<void> fetchTransactions() {
// return NetService.fetchJsonData(_serverUrl)
return NetService.fetchLocalJsonData()
.then((response) {
if (response != null) _trx = TransactionModel.fromJson(response);
})
.catchError((err) => print('Error!!!!! : $err'))
.whenComplete(() => _dataAvailable.value = _trx != null);
}
}
home_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_api/src/controllers/transaction_controller.dart';
class HomePage extends StatelessWidget {
/* ---------------------------------------------------------------------------- */
const HomePage({Key key}) : super(key: key);
/* ---------------------------------------------------------------------------- */
@override
Widget build(BuildContext context) {
final obj = Get.put(TransactionController());
return Scaffold(
appBar: buildAppBar(),
body: Obx(() => obj.dataAvailable
? Text(obj.trx.toString())
: Text('... waiting ...')),
);
}
/* ---------------------------------------------------------------------------- */
AppBar buildAppBar() {
return AppBar(
title: Text('Hi!'),
centerTitle: true,
);
}
}
transactions_data.dart
const transactionData = '''
{
"data": [
....
}
}
''';
Shoaib Khan
Updated on June 05, 2022Comments
-
Shoaib Khan almost 2 years
I am a newbie in the world of flutter and GetX package and I am trying to create a simple app using Laravel as my API service and I am sending the response from the API in JSON format and I am using Laravel resource API so it is sending some extra meta data inside the response and I have already created service model and controller in my flutter app but when I am initializing an observable variable in controller it is throwing a lot error i tried all the methods but it is working fine when i am sending only data list from the API as I have to define
List<Model>.obs
in controller but the problem is happening when i am sending the proper response from API as required.Here is my JSON response data from the API
{ "data": [ { "id": 1, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 2, "description": "Purchased mouse sa", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 3, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 4, "description": "Purchased mouse sa", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 5, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 6, "description": "Purchased mouse sa", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 7, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 8, "description": "Purchased mouse sa", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 9, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 10, "description": "Purchased mouse sa", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 11, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 12, "description": "Purchased mouse sa", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 13, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 14, "description": "Purchased mouse sa", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null }, { "id": 15, "description": "Purchased mouse", "amount": "1200", "type": "expense", "user_id": 1, "created_at": null, "updated_at": null } ], "links": { "first": "http://localhost:8000/api/transactions?page=1", "last": "http://localhost:8000/api/transactions?page=2", "prev": null, "next": "http://localhost:8000/api/transactions?page=2" }, "meta": { "current_page": 1, "from": 1, "last_page": 2, "links": [ { "url": null, "label": "« Previous", "active": false }, { "url": "http://localhost:8000/api/transactions?page=1", "label": 1, "active": true }, { "url": "http://localhost:8000/api/transactions?page=2", "label": 2, "active": false }, { "url": "http://localhost:8000/api/transactions?page=2", "label": "Next »", "active": false } ], "path": "http://localhost:8000/api/transactions", "per_page": 15, "to": 15, "total": 16 } }
And here is my service class
import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:m_budget/models/transaction.dart'; class TransactionService { static var client = http.Client(); static Future<Transaction> fetchTransactions() async { var res = await client.get("http://10.0.2.2:8000/api/transactions"); if (res.statusCode == 200) { return transactionFromJson(res.body); } else { return null; } } }
And this is my controller
The main problem is while declaring the observable variable check
line no 6 in controller
This one
var transactions = Transaction().obs;
import 'package:get/get.dart'; import 'package:m_budget/models/transaction.dart'; import 'package:m_budget/services/transaction_service.dart'; class TransactionController extends GetxController { var isLoading = true.obs; var transactions = Transaction().obs; @override void onInit() { fetchTransactions(); super.onInit(); } void fetchTransactions() async { isLoading(true); try { var txns = await TransactionService.fetchTransactions(); if (txns != null) { isLoading(false); transactions(txns); } } catch (e) {} finally { isLoading(false); } } }
And model code is this
// To parse this JSON data, do // // final transaction = transactionFromJson(jsonString); import 'dart:convert'; Transaction transactionFromJson(String str) => Transaction.fromJson(json.decode(str)); String transactionToJson(Transaction data) => json.encode(data.toJson()); class Transaction { Transaction({ this.data, this.links, this.meta, }); List<Datum> data; Links links; Meta meta; factory Transaction.fromJson(Map<String, dynamic> json) => Transaction( data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))), links: Links.fromJson(json["links"]), meta: Meta.fromJson(json["meta"]), ); Map<String, dynamic> toJson() => { "data": List<dynamic>.from(data.map((x) => x.toJson())), "links": links.toJson(), "meta": meta.toJson(), }; } class Datum { Datum({ this.id, this.description, this.amount, this.type, this.userId, this.createdAt, this.updatedAt, }); int id; String description; String amount; String type; int userId; dynamic createdAt; dynamic updatedAt; factory Datum.fromJson(Map<String, dynamic> json) => Datum( id: json["id"], description: json["description"], amount: json["amount"], type: json["type"], userId: json["user_id"], createdAt: json["created_at"], updatedAt: json["updated_at"], ); Map<String, dynamic> toJson() => { "id": id, "description": description, "amount": amount, "type": type, "user_id": userId, "created_at": createdAt, "updated_at": updatedAt, }; } class Links { Links({ this.first, this.last, this.prev, this.next, }); String first; String last; dynamic prev; String next; factory Links.fromJson(Map<String, dynamic> json) => Links( first: json["first"], last: json["last"], prev: json["prev"], next: json["next"], ); Map<String, dynamic> toJson() => { "first": first, "last": last, "prev": prev, "next": next, }; } class Meta { Meta({ this.currentPage, this.from, this.lastPage, this.links, this.path, this.perPage, this.to, this.total, }); int currentPage; int from; int lastPage; List<Link> links; String path; int perPage; int to; int total; factory Meta.fromJson(Map<String, dynamic> json) => Meta( currentPage: json["current_page"], from: json["from"], lastPage: json["last_page"], links: List<Link>.from(json["links"].map((x) => Link.fromJson(x))), path: json["path"], perPage: json["per_page"], to: json["to"], total: json["total"], ); Map<String, dynamic> toJson() => { "current_page": currentPage, "from": from, "last_page": lastPage, "links": List<dynamic>.from(links.map((x) => x.toJson())), "path": path, "per_page": perPage, "to": to, "total": total, }; } class Link { Link({ this.url, this.label, this.active, }); String url; dynamic label; bool active; factory Link.fromJson(Map<String, dynamic> json) => Link( url: json["url"] == null ? null : json["url"], label: json["label"], active: json["active"], ); Map<String, dynamic> toJson() => { "url": url == null ? null : url, "label": label, "active": active, }; } Please guys help me in this I am trying from last7 days but no success.