Flutter when clicked button will POST data to API but fail - flutter

I create food order app with flutter, but i found some error on my code when i try to create some button which works for POST data to API. I hope you guys can help me, your help is very useful for me, thank you
this is a response from API,
This is an example of the data that can be sent
{
"nominal_diskon": "50000",
"nominal_pesanan": "100000",
"items": [
{ "id": 1, "harga": 10000, "catatan": "Tes" },
{ "id": 2, "harga": 10000, "catatan": "Tes" },
{ "id": 3, "harga": 10000, "catatan": "Tes" }
]}
this is a transaction_service.dart
class TransactionService {
String baseUrl = 'https://tes-mobile.landa.id/api';
Future<bool> checkout(
double diskon, double totalprice, List<MenuModel> menus) async {
var url = '$baseUrl/order';
var body = jsonEncode(
{
'nominal_diskon': diskon,
'nominal_pesanan': totalprice,
'items': menus
.map(
(menu) =>
{'id': menu.id, 'harga': menu.harga, 'catatan': menu.catatan},
)
.toList(),
},
);
var response = await http.post(
Uri.parse(url),
body: body,
);
print(response.body);
if (response.statusCode == 200) {
return true;
} else {
throw Exception('Gagal Melakukan Checkout!');
}
}
}
this is a transaction_provider.dart
class TransactionProvider with ChangeNotifier {
Future<bool> checkout(
double diskon, double totalprice, List<MenuModel> menus) async {
try {
if (await TransactionService().checkout(diskon, totalprice, menus)) {
return true;
} else {
return false;
}
} catch (e) {
print(e);
return false;
}
}
}
this is a home_page.dart which runs the button
class HomePage extends StatefulWidget {
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String voucherCode = "";
#override
Widget build(BuildContext context) {
MenuProvider menuProvider = Provider.of<MenuProvider>(context);
VoucherProvider voucherProvider = Provider.of<VoucherProvider>(context);
TransactionProvider transactionProvider =
Provider.of<TransactionProvider>(context);
double hargaAkhir =
menuProvider.totalPrice() - voucherProvider.diskonHarga();
handleCheckout() async {
if (await transactionProvider.checkout(
10000,
100000,
menuProvider.menus,
)) {
Navigator.pushNamedAndRemoveUntil(
context, '/order-page', (route) => false);
}
}
Widget content() {
return ListView(
padding: EdgeInsets.symmetric(
horizontal: 25,
),
children: menuProvider.menus
.map(
(menu) => MenuCard(menu),
)
.toList(),
);
}
Widget customBottomNav() {
...
child: RaisedButton(
onPressed: handleCheckout,
child: Text('Pesan Sekarang',
style: whiteTextStyle.copyWith(
fontWeight: bold, fontSize: 14)),
color: menuProvider.totalItems() >= 1
? kPrimaryColor
: kDarkGreyColor,
textColor: kWhiteColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
side: BorderSide(
color: menuProvider.totalItems() >= 1
? Color(0xFF00717F)
: kDarkGreyColor,
width: 1,
),
),
),
)
],
),
),
],
),
);
}
return MaterialApp(
home: Scaffold(
backgroundColor: kWhiteColor,
body: content(),
bottomNavigationBar: customBottomNav(),
));
}
}

Related

flutter lazyload loading page twice

so im trying to build a lazyload, from my backend i already made per page 5 items. but i dont understand why when i try in flutter the first page is always loaded twice?
for example if i scroll up to page 5, the order of the page will be 1,1,2,3,4 then when i try to refresh, it will show page 5, refresh again then it will show page 1, any idea why?
class ProgressScreen extends StatefulWidget {
#override
_ProgressScreenState createState() => _ProgressScreenState();
}
class _ProgressScreenState extends State<ProgressScreen> {
late MainProgressStore _mainProgressStore;
late UserStore _userStore;
int currentPage = 1;
late int totalPages;
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
// initializing stores
_mainProgressStore = Provider.of<MainProgressStore>(context);
_userStore = Provider.of<UserStore>(context);
if (!_userStore.loading) {
_userStore.getUser();
}
if (!_mainProgressStore.loading) {
_mainProgressStore.postMainProgress(
'loading', 'all', 'desc', 3, 0, currentPage);
}
}
List<Datum> mainProgress = [];
final RefreshController refreshController =
RefreshController(initialRefresh: true);
Future<bool> getmainProgress({bool isRefresh = false}) async {
if (isRefresh) {
currentPage = 1;
} else {
if (currentPage >= totalPages) {
refreshController.loadNoData();
return false;
}
}
final response = await _mainProgressStore.postMainProgress(
'loading', 'all', 'desc', 3, 0, currentPage);
if (_mainProgressStore.success == true) {
final result = _mainProgressStore.mainProgress!.mainProgress;
if (isRefresh) {
mainProgress = result.response;
} else {
mainProgress.addAll(result.response);
}
currentPage++;
totalPages = 10;
print(result.response);
setState(() {});
return true;
} else {
return false;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppNavBar(),
drawer: DrawerNavBar(userStore: _userStore),
body: _buildMainContent(),
);
}
Widget _buildMainContent() {
return Observer(
builder: (context) {
return _mainProgressStore.success
? _buildRefresh(_mainProgressStore)
: CustomProgressIndicatorWidget();
},
);
}
Widget _buildRefresh(_mainProgressStore) {
return Platform.isIOS
? _buildIOSList(_mainProgressStore)
: _refreshView(_mainProgressStore);
}
Widget _refreshView(_mainProgressStore) {
return SmartRefresher(
controller: refreshController,
enablePullUp: true,
onRefresh: () async {
final result = await getmainProgress(isRefresh: true);
if (result) {
refreshController.refreshCompleted();
} else {
refreshController.refreshFailed();
}
},
onLoading: () async {
final result = await getmainProgress();
if (result) {
refreshController.loadComplete();
} else {
refreshController.loadFailed();
}
},
child: _buildBody(_mainProgressStore));
}
Widget _buildIOSList(_mainProgressStore) {
return Container(
child: CustomScrollView(
slivers: [
CupertinoSliverRefreshControl(
onRefresh: () async {
_mainProgressStore.getHomepage(currentPage);
},
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return _buildBody(_mainProgressStore);
}, childCount: _mainProgressStore.response.length))
],
),
);
}
Widget _buildBody(_mainProgressStore) {
return SingleChildScrollView(
child: Column(children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.only(
top: DeviceUtils.getScaledHeight(context, 0.03),
left: DeviceUtils.getScaledWidth(context, 0.06),
bottom: DeviceUtils.getScaledHeight(context, 0.03)),
child: Text(
'MY ORDERS',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: DeviceUtils.getScaledWidth(context, 0.035),
color: Colors.black),
),
),
),
SearchProgress(
currentPage: currentPage, mainProgressStore: _mainProgressStore),
OrderInfo(
progressData: mainProgress, mainProgressStore: _mainProgressStore),
]));
}
}

Flutter weird bug with widget function, sometimes in runs 2 times instead of one

This function have futureBuilder inside and returns another function that returns ListView.
Also I do not want the user to download information from the Internet every time they visit the page, so I put the information downloaded from the Internet into a static variable in class, so i make if else. If this static variable length != 0 , it return me listView instead of make server request with futureBuilder
function that works 2 times instead of one is ListView body
And also this bug created after i added purchases to my application, maybe something wrong there. I don't have any ideas why this happend
this is my complete code
class AddCheckList extends StatefulWidget {
const AddCheckList({Key? key}) : super(key: key);
#override
_AddCheckListState createState() => _AddCheckListState();
}
class _AddCheckListState extends State<AddCheckList> {
String xQueryReqestForCheckListNames = "element CheckListList {for \$a in PACK/OBJECT where (\$a/#inUse = 'True') order by \$a/#name return element CheckList {attribute name {\$a/#name}, attribute sPaid {\$a/#isPaid},attribute oid {\$a/#oid} }}";
String serverLink = "http...";
int addCheckListMethod = 0;
// if addCheckListMethod == 0, then data will download from server and checkLists will be added from server xml data
// if addCheckListMethod == 1, then data will download from assets, and checkLists will be added from assets xml data with getXmlData function
final InAppPurchase _inAppPurchase = InAppPurchase.instance;
final String _productID = '1d7ea644f690ffa';
bool _available = true;
List<ProductDetails> _products = [];
List<PurchaseDetails> _purchases = [];
StreamSubscription<List<PurchaseDetails>>? _subscription;
#override
void initState() {
final Stream<List<PurchaseDetails>> purchaseUpdated = _inAppPurchase.purchaseStream;
_subscription = purchaseUpdated.listen((purchaseDetailsList) {
setState(() {
_purchases.addAll(purchaseDetailsList);
_listenToPurchaseUpdated(purchaseDetailsList);
});
}, onDone: () {
_subscription!.cancel();
}, onError: (error) {
_subscription!.cancel();
});
_initialize();
super.initState();
}
#override
void dispose() {
_subscription!.cancel();
super.dispose();
}
void _initialize() async {
_available = await _inAppPurchase.isAvailable();
List<ProductDetails> products = await _getProducts(
productIds: Set<String>.from(
[_productID],
),
);
setState(() {
_products = products;
});
}
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
switch (purchaseDetails.status) {
case PurchaseStatus.pending:
// _showPendingUI();
break;
case PurchaseStatus.purchased:
case PurchaseStatus.restored:
// bool valid = await _verifyPurchase(purchaseDetails);
// if (!valid) {
// _handleInvalidPurchase(purchaseDetails);
// }
break;
case PurchaseStatus.error:
print(purchaseDetails.error!);
// _handleError(purchaseDetails.error!);
break;
default:
break;
}
if (purchaseDetails.pendingCompletePurchase) {
await _inAppPurchase.completePurchase(purchaseDetails);
}
});
}
Future<List<ProductDetails>> _getProducts({required Set<String> productIds}) async {
ProductDetailsResponse response = await _inAppPurchase.queryProductDetails(productIds);
return response.productDetails;
}
void _subscribe({required ProductDetails product}) {
final PurchaseParam purchaseParam = PurchaseParam(productDetails: product);
_inAppPurchase.buyNonConsumable(
purchaseParam: purchaseParam,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(padding: EdgeInsets.all(14.0), child: listViweBody(addCheckListMethod, serverLink, xQueryReqestForCheckListNames, _products,_subscribe)),
);
}
}
Widget listView(addCheckListMethod, serverLink, product,_subscribe) {
return ListView.separated(
itemCount: CheckListModel.checkListModelNamesFromServer.length,
itemBuilder: (BuildContext context, int index) {
if (CheckListModel.checkListModelNamesFromServer[index].ispaid == false) {
return InkWell(
onTap: () async {
CheckListModel checkList = CheckListModel('', 0, '', 0, 0, 0, '', [], '');
if (addCheckListMethod == 0) {
String xQueryReqestForCheckList = 'for \$a in PACK/OBJECT where \$a/#name="${CheckListModel.checkListModelNamesFromServer[index].name}" return \$a';
var data = await CheckListModel.getDataFromServer(xQueryReqestForCheckList, serverLink);
CheckListModel.addCheckListFromServer(checkList, data);
} else {
CheckListModel.addCheckList(index, checkList);
}
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Добавить описание"),
content: Container(
decoration: BoxDecoration(border: Border.all(color: Color.fromARGB(Desing.colorFromARGBBtn[0], Desing.colorFromARGBBtn[1], Desing.colorFromARGBBtn[2], Desing.colorFromARGBBtn[3]), width: 1), borderRadius: BorderRadius.circular(10)),
child: TextField(
decoration: new InputDecoration.collapsed(hintText: "Описание", border: InputBorder.none),
maxLines: null,
onChanged: (String value) async {
checkList.description = value;
},
),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Отменить"),
),
TextButton(
onPressed: () async {
await checkList.writeToFile(checkList.toJson());
CheckListModel.checkLists.add(checkList);
Navigator.pushNamed(context, '/beforeMainCheckList', arguments: {'index': CheckListModel.checkLists.length - 1});
},
child: Text('Добавить'))
],
);
});
},
child: Container(
decoration: BoxDecoration(border: Border.all(color: Color.fromARGB(Desing.colorFromARGBBtn[0], Desing.colorFromARGBBtn[1], Desing.colorFromARGBBtn[2], Desing.colorFromARGBBtn[3]), width: 1), borderRadius: BorderRadius.circular(10)),
width: 50,
height: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"${CheckListModel.checkListModelNamesFromServer[index].name}",
style: TextStyle(fontSize: 30),
)
],
),
),
);
} else {
if (product.length != 0) {
return showPurchaseCheckLists(product, index,_subscribe);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}
},
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 14,
);
});
}
Widget showPurchaseCheckLists(product, index,_subscribe) {
int getCurrentProduct() {
String? checkListModelid = CheckListModel.checkListModelNamesFromServer[index].checkListId?.toLowerCase();
int indexx = 0;
for (int i = 0; i < product.length; i++) {
if (checkListModelid == product[i].id) {
indexx = i;
}
}
return indexx;
}
return InkWell(
child: Container(
decoration: BoxDecoration(border: Border.all(color: Color.fromARGB(Desing.colorFromARGBBtn[0], Desing.colorFromARGBBtn[1], Desing.colorFromARGBBtn[2], Desing.colorFromARGBBtn[3]), width: 1), borderRadius: BorderRadius.circular(10), color: Color.fromARGB(255, 240, 240, 240)),
width: 50,
height: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"${CheckListModel.checkListModelNamesFromServer[index].name}",
style: TextStyle(fontSize: 25),
),
Text("Купить за ${product[getCurrentProduct()].price}")
],
),
),
onTap: () {
_subscribe(product: product[getCurrentProduct()]);
},
);
}
Widget listViweBody(addCheckListMethod, serverLink, xQueryReqestForCheckListNames, product,_subscribe) {
if (CheckListModel.checkListModelNamesFromServer.length == 0) {
return FutureBuilder(
future: CheckListModel.getDataFromServer(xQueryReqestForCheckListNames, serverLink),
builder: (context, data) {
if (data.connectionState == ConnectionState.done) {
return listView(addCheckListMethod, serverLink, product,_subscribe);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
} else {
return listView(addCheckListMethod, serverLink, product,_subscribe);
}
}

how to implement search listview in flutter

bloc.dart
part 'news_article_loader_event.dart';
part 'news_article_loader_state.dart';
part 'news_article_loader_bloc.freezed.dart';
#injectable
class NewsArticleLoaderBloc
extends Bloc<NewsArticleLoaderEvent, NewsArticleLoaderState> {
NewsArticleLoaderBloc(this.iBlogPost)
: super(NewsArticleLoaderState.initial());
final INewsArticle iBlogPost;
#override
Stream<NewsArticleLoaderState> mapEventToState(
NewsArticleLoaderEvent event) async* {
yield NewsArticleLoaderState.loadInProgress();
final failureOrSuccess = await iBlogPost.getDataNews();
yield failureOrSuccess.fold((l) => NewsArticleLoaderState.loadFailure(l),
(r) => NewsArticleLoaderState.loadSuccess(r));
}
}
repository.dart
import 'dart:convert';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:mone/app_constant.dart';
import 'package:mone/model/news/blog_post.dart';
import 'package:mone/repositories/i_news_repository.dart';
import 'package:shared_preferences/shared_preferences.dart';
#Injectable(as: INewsArticle)
class BLogPostRepository implements INewsArticle {
final Dio dio;
// int page = 1;
final SharedPreferences prefs;
BLogPostRepository(this.dio, this.prefs);
#override
Future<Either<String, List<NewsBlogModel>>> getDataNews() async {
try {
final token = prefs.get(kAccesTokenKey);
String url = '/api/v1/cms?size=30';
var response = await dio.get(url,
options: Options(
headers: {
'Accept': 'aplication/json',
'Authorization': 'bearer $token',
},
));
if (response.statusCode == 200) {
final listNews = (response.data['items'] as List)
.map((e) => NewsBlogModel.fromJson(e as Map<String, dynamic>))
.toList();
return right(listNews);
}
return left('error: ${response.statusCode}');
} catch (e) {
return left('error get data $e');
}
}
#override
Future<Either<String, List<NewsBlogModel>>> getDataNewsbyId() async {
// TODO: implement getDataNewsbyId
try {
final token = prefs.get(kAccesTokenKey);
String urlbyid = '/api/v1/cms/id';
var response = await dio.get(urlbyid,
options: Options(headers: {
'Accept': 'aplication/json',
'Authorization': 'bearer $token',
}));
if (response.statusCode == 200) {
final dataNewsbyId = (response.data['items'] as List)
.map((e) => NewsBlogModel.fromJson(e as Map<String, dynamic>))
.toList();
return right(dataNewsbyId);
}
return left("error:${response.statusCode}");
} catch (e) {
return left("error get data $e");
}
}
}
I have the code below where I have provided the BLoC code for the code and also for the repository code. but I'm still confused about how to connect it to the UI that I made. explanation please.
below also my code has succeeded to call all data list from API. but when I want to try to find the data list in the get, but can't.
UI.dart
part of '../screens.dart';
class NewsScreen extends StatefulWidget {
#override
_NewsScreenState createState() => _NewsScreenState();
}
class _NewsScreenState extends State<NewsScreen> {
Widget customTitleBar = const Text('Berita');
Icon customIcon = new Icon(Icons.search, color: primaryColor);
TextEditingController filterController = TextEditingController();
// String filter = '';
// void initState(){
// }
#override
Widget build(BuildContext context) {
// bloc provider berguna untuk menambahkan data dari bloc ke ui,
return BlocProvider(
create: (context) =>
getIt<NewsArticleLoaderBloc>()..add(NewsArticleLoaderEvent.started()),
child: Scaffold(
appBar: AppBar(
title: customTitleBar,
actions: <Widget>[
IconButton(
onPressed: () {
setState(() {
if (this.customIcon.icon == Icons.search) {
this.customIcon =
new Icon(Icons.close, color: primaryColor, size: 30);
this.customTitleBar = new TextField(
style: new TextStyle(
color: Colors.white,
),
decoration: new InputDecoration(
prefixIcon: new Icon(Icons.search,
color: primaryColor, size: 30),
hintText: "Search...",
hintStyle: new TextStyle(color: Colors.white)),
cursorColor: primaryColor,
onChanged: (value) async {
if (value.isEmpty) {
setState(() {});
return;
}
},
controller:filterController,
);
} else {
this.customIcon =
new Icon(Icons.search, color: primaryColor, size: 30);
this.customTitleBar = new Text("Berita");
}
});
},
icon: customIcon,
),
],
),
body: BlocBuilder<NewsArticleLoaderBloc, NewsArticleLoaderState>(
builder: (context, state) {
return state.map(
initial: (_) => Container(),
loadInProgress: (_) => Center(
child: SpinKitCircle(
color: primaryColor,
),
),
loadFailure: (state) => Center(
child: Text(state.failure),
),
loadSuccess: (state) {
if (state.datenews.isEmpty) {
return Center(
child: Text("data tidak di temukan"),
);
} else {
return ListView.separated(
padding: EdgeInsets.all(8.0),
itemCount: state.datenews.length,
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 4,
);
},
itemBuilder: (BuildContext context, int index) {
final newsBlog = state.datenews[index];
return ContentNews(
newsBlog: newsBlog,
);
},
);
}
},
);
},
),
),
);
}
}

What is my mistake with Flutter Provider Architecture, since it keeps rebuilding infinintly?

What am I mistaking with provider architecture?
My EntryPoint:
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<AuthProvider>(
create: (context) => AuthProvider()),
ChangeNotifierProvider<UserProvider>(
create: (context) => UserProvider()),
],
child: BdopsApp(),
),
);
}
class BdopsApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.teal,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
initialRoute: LoginView.routeName,
routes: {
HomepageView.routeName: (context) => HomepageView(),
LoginView.routeName: (context) => LoginView(),
},
);
}
}
First I have logged in with my log in credentials.
class LoginView extends StatelessWidget {
static const routeName = 'LoginView';
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final User _user = User();
#override
Widget build(BuildContext context) {
return Consumer<AuthProvider>(
builder: (_, data, __) => Scaffold(
appBar: CustomAppBar.getAppBar(
title: 'BDOPS',
subTitle: 'LOG IN',
),
drawer: SidveNavDrawer(),
body: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FormInputTextBox(
labelText: 'Email',
hintText: 'example#domain.com',
validator: (value) {
if (value == null) {
return 'Login email not provided';
}
if (!RegExp(xEmailRegx).hasMatch(value)) {
return 'Not a valid email address';
}
},
onSaved: (value) {
_user.email = value.trim();
},
),
FormInputTextBox(
labelText: 'Password',
hintText: '* * * * *',
isPassword: true,
validator: (value) {
if (value == null) {
return 'Login password not provided';
}
if (value.toString().length < 6) {
return 'Minmum length is six charector';
}
},
onSaved: (value) {
_user.password = value.trim();
},
),
Divider(
height: 30.0,
),
RaisedButton(
color: Colors.deepOrange,
padding: EdgeInsets.symmetric(vertical: 10.0),
onPressed: () async {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
var res = await data.loginUser(_user);
if (res == true) {
AlertDialog(
title: Text('Login Success'),
);
} else {
AlertDialog(
title: Text('Login Failed'),
);
}
Navigator.pushReplacementNamed(
context, HomepageView.routeName);
},
child: Text(
'SUBMIT',
style: xHeaderText,
),
),
],
),
),
),
),
);
}
}
Than I navigated to the home page where on page load the screen should grab Auth user from AuthUser Provider's getAuthUser and self trigger a method to fetch logged in user's detail from the API with the userID.
class HomepageView extends StatelessWidget {
static const routeName = 'HomePageView';
#override
Widget build(BuildContext context) {
final userId = Provider.of<AuthProvider>(context).getAuthUser.id;
return Consumer<UserProvider>(
builder: (_, dataProvider, __) {
dataProvider.fetchAUser(userId);
return Scaffold(
appBar: CustomAppBar.getAppBar(title: 'BDOPS', subTitle: 'Home'),
drawer: SidveNavDrawer(),
body: Text(dataProvider.getSingelUser.email),
);
},
);
}
}
Doing this, my app at first throws an error and than keeps rebuilding and calling the API over and over again.
My Provider Classes Are:
class AuthProvider with ChangeNotifier {
User _authUser;
String _errorMessage;
AuthTokens _tokens;
Future<bool> loginUser(User user) async {
if (user.email == null || user.password == null) {
_setErrorMessage('Provide login credentials');
}
var resp = await APIService().loginUser(
email: user.email,
password: user.password,
);
if (resp.statusCode == 200) {
_setAuthToken(authTokensFromJson(resp.body));
var userFetched =
await UserProvider().fetchAUser(decodeJwt(_tokens.access)['user_id']);
if (userFetched != null) {
_setAuthUser(userFetched);
return true;
}
}
_setErrorMessage('Failed to login');
return false;
}
void _setAuthToken(value) {
_tokens = value;
}
void _setAuthUser(value) {
_authUser = value;
notifyListeners();
}
User get getAuthUser {
return _authUser;
}
void _setErrorMessage(value) {
_errorMessage = value;
notifyListeners();
}
String get getErrorMessage {
return _errorMessage;
}
}
class UserProvider with ChangeNotifier {
User _user;
Future<User> fetchAUser(userId) async {
var response = await APIService().getAUser(userId: userId);
if (response.statusCode == 200) {
setUser(userFromJson(response.body));
print('Called from UserProvider');
return _user;
}
return null;
}
void setUser(value) {
_user = value;
notifyListeners();
}
User get getSingelUser {
return _user;
}
}

Flutter : Prepare list data from http request

I am trying to use Flutter Tagging Plugin (https://github.com/sarbagyastha/flutter_tagging). During the testing it is working fine with hard coded list. Now, I am changing it to make call to database and show the list based on that.
Database is returning the data and JSON Parse is also showing the data.
However, I am not able to use that data in Flutter Tagging. As I do not have good knowledge on Flutter.
Here is the code which is working fine when using hard-coded list.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_syntax_view/flutter_syntax_view.dart';
import 'package:flutter_tagging/flutter_tagging.dart';
void main() => runApp(MyApp());
///
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Tagging Demo',
theme: ThemeData(
primarySwatch: Colors.green,
scaffoldBackgroundColor: Colors.white,
),
home: MyHomePage(),
);
}
}
///
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _selectedValuesJson = 'Nothing to show';
List<Language> _selectedLanguages;
#override
void initState() {
_selectedLanguages = [];
super.initState();
}
#override
void dispose() {
_selectedLanguages.clear();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Tagging Demo'),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: FlutterTagging<Language>(
initialItems: _selectedLanguages,
textFieldConfiguration: TextFieldConfiguration(
decoration: InputDecoration(
border: InputBorder.none,
filled: true,
fillColor: Colors.green.withAlpha(30),
hintText: 'Search Tags',
labelText: 'Select Tags',
),
),
findSuggestions: LanguageService.getLanguages,
additionCallback: (value) {
return Language(
name: value,
position: 0,
);
},
onAdded: (language) {
// api calls here, triggered when add to tag button is pressed
return Language();
},
configureSuggestion: (lang) {
return SuggestionConfiguration(
title: Text(lang.name),
subtitle: Text(lang.position.toString()),
additionWidget: Chip(
avatar: Icon(
Icons.add_circle,
color: Colors.white,
),
label: Text('Add New Tag'),
labelStyle: TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.w300,
),
backgroundColor: Colors.green,
),
);
},
configureChip: (lang) {
return ChipConfiguration(
label: Text(lang.name),
backgroundColor: Colors.green,
labelStyle: TextStyle(color: Colors.white),
deleteIconColor: Colors.white,
);
},
onChanged: () {
setState(() {
_selectedValuesJson = _selectedLanguages
.map<String>((lang) => '\n${lang.toJson()}')
.toList()
.toString();
_selectedValuesJson =
_selectedValuesJson.replaceFirst('}]', '}\n]');
});
},
),
),
SizedBox(
height: 20.0,
),
Expanded(
child: SyntaxView(
code: _selectedValuesJson,
syntax: Syntax.JAVASCRIPT,
withLinesCount: false,
syntaxTheme: SyntaxTheme.standard(),
),
),
],
),
);
}
}
/// LanguageService
class LanguageService {
/// Mocks fetching language from network API with delay of 500ms.
static Future<List<Language>> getLanguages(String query) async {
await Future.delayed(Duration(milliseconds: 500), null);
return <Language>[
Language(name: 'JavaScript', position: 1),
Language(name: 'Python', position: 2),
Language(name: 'Java', position: 3),
Language(name: 'PHP', position: 4),
Language(name: 'C#', position: 5),
Language(name: 'C++', position: 6),
]
.where((lang) => lang.name.toLowerCase().contains(query.toLowerCase()))
.toList();
}
}
/// Language Class
class Language extends Taggable {
///
final String name;
///
final int position;
/// Creates Language
Language({
this.name,
this.position,
});
#override
List<Object> get props => [name];
/// Converts the class to json string.
String toJson() => ''' {
"name": $name,\n
"position": $position\n
}''';
}
I have create a http request function as below.
class LanguageService {
/// Mocks fetching language from network API with delay of 500ms.
static Future<List<Taggable>> getLanguages(String query) async {
List searchlists = [];
String searchvalue = query;
var dtguid = 10;
var dtgname = 'Test';
int count = 0;
String nodata;
await Future.delayed(Duration(seconds: 1), null);
if(searchvalue.length > 2 && searchvalue.length < 15 ){
searchlists.clear();
try{
var deviceid = '1234';
var dtgUid = '10';
dtguid = dtgUid;
print(searchvalue);
var body = { "uid" : dtgUid, "deviceid": deviceid, "searchtext": searchvalue};
var url = 'http://192.168.100.4:8080/search_tags.php';
// Starting Web API Call.
var response = await http.post(url, body: json.encode(body)).timeout(Duration(seconds: 5),
onTimeout: (){
return null;
});
if(response.statusCode == 200){
final data = getTagsFromJson(response.body);
var totalrec = data.content.length;
print('hi $totalrec');
if(data.content.length > 0 && data.content[0].tagname != 'Empty'){
for (var i in data.content) {
searchlists.add(i);
print(i.tagname);
}
}else{
nodata = 'No Record Found';
}
print(searchlists.length);
}
}catch(e){
print("Exception Caught: $e");
}
return searchlists;
}else{
return null;
}
Here is the JSON Parse File.
GetTags getTagsFromJson(String str) => GetTags.fromJson(json.decode(str));
class GetTags {
List<Content> content;
bool success;
String error;
GetTags({
this.error,
this.content,
this.success,
});
factory GetTags.fromJson(Map<String, dynamic> json) => GetTags(
error: json["error"],
content: (json["content"] as List).map((x) => Content.fromJson(x)).toList(),
success: json["success"],
);
}
class Content {
String tagname;
Content({
this.tagname,
});
factory Content.fromJson(Map<String, dynamic> json) => Content(
tagname: json == null ? 'Empty' : json["tagname"]
);
}