import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import '../models/product.dart';
class DbHelper {
late Database ?_db;
static final DbHelper instance=DbHelper();
Future<Database> get db async{
if(_db==null){
_db=await initializedb();
}
return _db!;
}
static Future<Database> initializedb()async {
String dbPath = join(await getDatabasesPath(),"etrade.db");
var etradeDB = await openDatabase(dbPath,version: 1,onCreate: createDb);
return etradeDB;
}
void createDb(Database db, int version)async {
await db.execute("Create table products(id integer primary key, name text, description
text, unitPrice integer)");
}
Future<List<Product>> getProducts() async{
Database db = await this.db;
var result = await db.query("products");
return List.generate(result.length, (i){
return Product.fromObject(result[i]);
});
}
Future<int> insert(Product product) async {
Database db = await this.db;
var result = await db.insert("products",product.toMap());
return result;
}
Future<int> delete(int id) async {
var db = await this.db;
var result = await db.rawDelete("delete from products where id=$id");
return result;
}
Future<int> update(Product product) async {
var db = await this.db;
var result = await db.update("product", product.toMap(), where: "id=?",whereArgs:
[product.id]);
return result;
}
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sqflite_demo/data/dbHelper.dart';
class ProductAdd extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return ProductAddState();
}
}
class ProductAddState extends State with DbHelper{
initState() {
myAsyncInit();
}
myAsyncInit() async {
//do async stuff
}
var Dbhelper = DbHelper;
final txtName = TextEditingController();
final txtDescription = TextEditingController();
var txtUnitPrice = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text("Yeni Ürün ekle"),
),
body: Padding(
padding: EdgeInsets.all(30.0),
child: Column(
children: <Widget>[
buildNameField(),
buildDescriptionField(),
buildUnitPriceField(),
buildSaveButton()
],
),
),
);
}
buildUnitPriceField() {
return TextField(
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
decoration: InputDecoration(labelText: "Birim fiyatı", hintText: "20"),
controller: txtName,
);
}
buildNameField() {
return TextField(
decoration: InputDecoration(labelText: "Ürün adı", hintText: "Tohum"),
controller: txtDescription,
);
}
buildDescriptionField() {
return TextField(
decoration: const InputDecoration(
labelText: "Ürün açıklaması", hintText: "Domates"),
controller: txtUnitPrice,
);
}
buildSaveButton() {
return FlatButton(
onPressed: () {
addProduct();
},
child: const Text("Ekle"),
);
}
void addProduct() async {
await Dbhelper.insert;
}
}
I want to call insert from the db helper below, the error it gives is as follows
The getter 'insert' isn't defined for the type 'Type'. (Documentation) Try importing the library that defines 'insert', correcting the name to the name of an existing getter, or defining a getter or field named 'insert'.
First if you want to create a singleton class do it like this,
class DbHelper {
static final DbHelper instance= DbHelper._();//change to this
...
}
second,
When using singleton no need to create it's instance,
initialise that class in main or some root widget.
like this,
void main()async{
await DbHelper.init();
...
}
third, now where you want to use this functions,
class ProductAdd extends StatefulWidget {
const ProductAdd({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _ ProductAddState();
}
class _ ProductAddState extends State< ProductAdd> {
// you actually don't need "mixin" just directly use it.
...
void addProduct() async {
await Dbhelper.insert();
}
}
}
more about singleton,
How do you build a Singleton in Dart?
Related
Guys how to transfer data when I login.. For example when I login the transfer data are User ID, email and password.. So if I want to add something that requires the user id how do I call it?
This is my login method
void login() async {
if(passController.text.isNotEmpty && emailController.text.isNotEmpty) {
var response = await http.post(
Uri.parse("url"),
body: ({
'email': emailController.text,
'password': passController.text,
}));
if (response.statusCode == 200) {
final body = jsonDecode(response.body);
print(body.toString());
List<dynamic> data = body["Details"];
print(data[0]['email']);
pageRoute(data[0]['name']);
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Wrong password")));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Sila isi tempat kosong")));
}
}
void pageRoute(data) async {
//STORE VALUE IN SHARED PREFERENCES
SharedPreferences pref = await SharedPreferences.getInstance();
await pref.setString("login", data);
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => nav()),
(route) => false);
This is where I want to take the user id without put it on the textfield.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import '../Utils/lib.dart';
class CarList extends StatefulWidget {
const CarList({Key? key}) : super(key: key);
#override
State<CarList> createState() => _CarListState();
}
class _CarListState extends State<CarList> {
var userController = TextEditingController();
// late SharedPreferences logindata;
// String? Email;
final pref = Pref();
// late String name;
// late String registeration_no;
#override
void initState() {
// TODO: implement initState
super.initState();
initial();
}
void initial() async {
if (pref.isLogin()) {
final body = jsonDecode(pref.getLogin());
print(body['Details']['user_id'].toString());
}
return null;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: <Widget>[
Container(
padding: const EdgeInsets.all(10),
child: TextField(
controller: userController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
suffixIcon: Icon(Icons.email),
labelText: 'User ID',
),
),
),
Container(
margin: EdgeInsets.all(25),
child: TextButton(
child: Text('test',
style: TextStyle(fontSize: 20.0,
color: Colors.blueAccent,
backgroundColor: Colors.white),
),
onPressed: () {
list();
},
),
)
]
)
);
}
void list() async {
{
var response = await http.post(
Uri.parse("url"),
body: ({
'user_id': userController.text,
}));
if (response.statusCode == 200) {
final body = jsonDecode(response.body);
// final SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
// sharedPreferences.setString('email', emailController.text);
pref.saveLogin(true, response.body);
print(body.toString());
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Successfully Login")));
}
}
}
}
Im kinda new with this flutter so might thankful with your help
You can do something like this:
This is store data in pageRoute.
void login() async {
if (passController.text.isNotEmpty && emailController.text.isNotEmpty) {
var response = await http.post(
Uri.parse("http://servisjer.me-tech.com.my/api/Login"),
body: ({
'email': emailController.text,
'password': passController.text,
}));
if (response.statusCode == 200) {
final body = jsonDecode(response.body);
print(body.toString());
List<dynamic> data = body["Details"];
print(data[0]['email']);
pageRoute(Data(data[0]['email'], data[0]['user_id']));
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Wrong password")));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Sila isi tempat kosong")));
}
}
void pageRoute(Data data) async {
MySharedPreferences().storeUser(data);
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => nav()), (route) => false);
}
MySharedPreferences
class MySharedPreferences {
Future<void> storeUser(Data data) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("email", data.email);
prefs.setInt("user_id", data.userId);
}
Future getUserId() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var userId = prefs.getInt("user_id");
return userId;
}
}
In CarList, retrieve data using this way
#override
void initState() {
MySharedPreferences().getUserId().then((value) {
setState(() {
userController.text = value.toString();
});
});
//TODO: IMPLEMENT INITSTATE
super.initState();
}
Data
class Data {
var email;
var userId;
Data(this.email,this.userId);
}
ERROR:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following ProviderNotFoundException was thrown building AuthPage(dirty, state:
_AuthPageState#7ac1c):
Error: Could not find the correct Provider above this AuthPage Widget
This happens because you used a BuildContext that does not include the provider
of your choice. There are a few common scenarios:
You added a new provider in your main.dart and performed a hot-reload.
To fix, perform a hot-restart.
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that AuthPage is under your MultiProvider/Provider.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
consider using builder like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}
My Code:
AuthPage.dart:-
import 'package:first_app/pages/auth/bloc/auth_state.dart';
import 'package:first_app/pages/auth/widgets/auth_button.dart';
import 'package:first_app/pages/auth/widgets/otp_page.dart';
import 'package:first_app/pages/auth/widgets/phone_page.dart';
import 'package:first_app/pages/auth/widgets/set_up_account.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
class AuthPage extends StatefulWidget {
final int page;
final String? uid;
const AuthPage({
Key? key,
this.page = 0,
this.uid,
}) : super(key: key);
#override
_AuthPageState createState() => _AuthPageState();
}
class _AuthPageState extends State<AuthPage> {
#override
Widget build(BuildContext context) {
final state = Provider.of<AuthState>(context);
final screenSize = MediaQuery.of(context).size;
return
Builder(builder: (context) {
return Stack(
children: [
Container(
height: screenSize.height,
width: screenSize.width,
color: Colors.white,
child: PageView(
controller: state.controller,
onPageChanged: state.onPageChanged,
physics: NeverScrollableScrollPhysics(),
children: [
PhonePage(),
OtpPage(),
SetUpAccount(),
],
),
),
AuthButton(),
],
);
});
}
}
class AuthPageWidget extends StatelessWidget {
final int page;
final String? uid;
const AuthPageWidget({
Key? key,
required this.page,
this.uid,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final state = AuthState(page, uid ?? '');
return ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
);
}
}
AuthState.dart
import 'dart:async';
import 'package:first_app/models/user.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/services/auth.dart';
import 'package:first_app/services/map_services.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
enum PhoneAuthState { initial, success, loading, codeSent, error }
/*part of 'auth_bloc.dart';
abstract class AuthState extends Equatable {
const AuthState();
#override
List<Object> get props => [];
}*/
class AuthState extends ChangeNotifier {
final authService = AuthService.instance;
final userRepo = UserRepository.instance;
PhoneAuthState _phoneAuthState = PhoneAuthState.initial;
String verificationId = '';
TextEditingController phoneController = TextEditingController();
TextEditingController otpController = TextEditingController();
TextEditingController firstNameController = TextEditingController();
TextEditingController lastNameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController licensePlateController = TextEditingController();
TextEditingController vehicleColorController = TextEditingController();
TextEditingController vehicleTypeController = TextEditingController();
TextEditingController vehicleManufacturersController = TextEditingController();
Roles role = Roles.passenger;
PageController? controller;
int pageIndex = 0;
String uid = '';
int timeOut = 30;
bool get isRoleDriver => role == Roles.driver;
AuthState(int page, String uid) {
this.uid = uid;
controller = PageController(initialPage: page);
pageIndex = page;
notifyListeners();
siginCurrentUser();
}
PhoneAuthState get phoneAuthState => _phoneAuthState;
set changeRoleState(int value) {
role = Roles.values[value];
notifyListeners();
}
set phoneAuthStateChange(PhoneAuthState phoneAuthState) {
_phoneAuthState = phoneAuthState;
notifyListeners();
}
void animateToNextPage(int page) {
controller!.animateToPage(page, duration: Duration(milliseconds: 400), curve: Curves.easeIn);
pageIndex = page;
notifyListeners();
}
void onPageChanged(int value) {
pageIndex = value;
notifyListeners();
}
Future<void> signUp() async {
phoneAuthStateChange = PhoneAuthState.loading;
final address = await MapService.instance?.getCurrentPosition();
try {
final user = User(
uid: uid,
isActive: true,
firstname: firstNameController.text,
lastname: lastNameController.text,
email: emailController.text,
createdAt: DateTime.now(),
isVerified: true,
licensePlate: licensePlateController.text,
phone: "234${phoneController.text}",
vehicleType: vehicleTypeController.text,
vehicleColor: vehicleColorController.text,
vehicleManufacturer: vehicleManufacturersController.text,
role: role,
latlng: address?.latLng,
);
await userRepo.setUpAccount(user);
phoneAuthStateChange = PhoneAuthState.success;
} on FirebaseException catch (e) {
print(e.message);
phoneAuthStateChange = PhoneAuthState.error;
}
}
Future<void> phoneNumberVerification(String phone) async {
await AuthService.instance!.verifyPhoneSendOtp(phone, completed: (credential) async {
if (credential.smsCode != null && credential.verificationId != null) {
verificationId = credential.verificationId ?? '';
notifyListeners();
await verifyAndLogin(credential.verificationId!, credential.smsCode!, phoneController.text);
}
}, failed: (error) {
phoneAuthStateChange = PhoneAuthState.error;
}, codeSent: (String id, int? token) {
verificationId = id;
notifyListeners();
phoneAuthStateChange = PhoneAuthState.codeSent;
codeSentEvent();
print('code sent $id');
}, codeAutoRetrievalTimeout: (id) {
verificationId = id;
notifyListeners();
phoneAuthStateChange = PhoneAuthState.codeSent;
animateToNextPage(1);
print('timeout $id');
});
animateToNextPage(1);
notifyListeners();
}
Future<void> verifyAndLogin(String verificationId, String smsCode, String phone) async {
phoneAuthStateChange = PhoneAuthState.loading;
final uid = await authService?.verifyAndLogin(verificationId, smsCode, phone);
await userRepo.getUser(uid);
this.uid = uid ?? '';
animateToNextPage(2);
notifyListeners();
phoneAuthStateChange = PhoneAuthState.success;
print('completed');
}
Future<void> siginCurrentUser() async {
await userRepo.signInCurrentUser();
}
Future<void> codeSentEvent() async {
animateToNextPage(1);
_startCountDown();
}
void _startCountDown() {
Timer.periodic(Duration(seconds: 1), (timer) {
if (timer.tick > 30) {
timer.cancel();
} else {
--timeOut;
}
notifyListeners();
});
}
}
main.dart
import 'package:first_app/pages/home/home.dart';
import 'package:first_app/repositories/user_repository.dart';
import 'package:first_app/ui/theme.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
UserRepository.instance.signInCurrentUser();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BrilliantDrive',
theme: CityTheme.theme,
home: HomePage(),
);
}
}
Initialize your provider 1st. Refer this https://stackoverflow.com/a/68418866/16467763.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<AuthState>(
create: (context) => AuthState(),
),
],
child: MyApp(),
),
);
}
class AuthPageWidget extends StatelessWidget {
final int page;
final String? uid;
const AuthPageWidget({
Key? key,
required this.page,
this.uid,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final state = AuthState(page, uid ?? '');
return ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
);
}
}
You should move the ChangeNotifierProvider to your main.dart like this
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final state = AuthState(page, uid ?? '');
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (_) => state,
child: AuthPage(page: page, uid: uid),
),
),
);
}
OR
class SomeWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (_) => state,
child: ChangeNotifierProvider.value(
value: state,
child: AuthPage(page: page, uid: uid),
),
)
),
);
}
}
I folowed this video to implement localization in my app :- https://youtu.be/Zw4KoorVxgg
Everything works fine but when the app is relaunched the language gets set to default. How can I persiste the data.
[Note:- I am already using shared preference to persist some other data in my app, but I have no clue about persisting selected Locale]
This class below is called to set the locale:
class LocaleProvider extends ChangeNotifier {
Locale? _locale;
Locale? get locale => _locale;
void setLocale(Locale locale) {
if (!L10n.all.contains(locale)) return;
_locale = locale;
notifyListeners();
}
void clearLocale() {
_locale = null;
notifyListeners();
}
}
And this is the screen where I set the language:
class SelectLanguage extends StatefulWidget {
const SelectLanguage({Key? key}) : super(key: key);
#override
_SelectLanguageState createState() => _SelectLanguageState();
}
class _SelectLanguageState extends State<SelectLanguage> {
void setLocale(String selectedLocale) {
final provider = Provider.of<LocaleProvider>(context, listen: false);
provider.setLocale(
Locale(selectedLocale),
);
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.black,
body: Padding(
padding:
EdgeInsets.all(MediaQuery.of(context).size.width / 41.1),
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 2.75,
crossAxisSpacing: MediaQuery.of(context).size.width / 41.1,
mainAxisSpacing: MediaQuery.of(context).size.width / 41.1,
),
children: [
LanguageTile(
tileTitle: 'English',
titleOnTap: () => setLocale('en'),
),
LanguageTile(
tileTitle: 'हिन्दी',
titleOnTap: () => setLocale('hi'),
),
],
),
),
),
);
}
}
using shared preference
static Future<Locale> setLocale(String langCode) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(languageCode, langCode);
return locale(langCode);
}
static Locale locale(String languageCode) {
Locale _temp;
if (languageCode == 'hi') {
_temp = Locale('hi');
}
else {
_temp = Locale('en');
}
return _temp;
}
static Future<Locale> getLocale() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String code = prefs.getString(languageCode);
print('language code:$code');
return locale(code);
}
create a class
import 'dart:ui';
import 'package:shared_preferences/shared_preferences.dart';
const String LAGUAGE_CODE = 'languageCode';
//languages code
const String ENGLISH = 'en';
const String FRENCH = 'fr';
const String ARABIC = 'ar';
const String KINYARWANDA = 'rw';
const String SWAHILLI ="sw";
Future<Locale> storeLocale(String languageCode) async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
await _prefs.setString(LAGUAGE_CODE, languageCode);
return _locale(languageCode);
}
Future<Locale> getLocale() async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
String languageCode = _prefs.getString(LAGUAGE_CODE) ?? ENGLISH;
return _locale(languageCode);
}
Locale _locale(String languageCode) {
switch (languageCode) {
case ENGLISH:
return const Locale(ENGLISH, '');
case FRENCH:
return const Locale(FRENCH, "");
case ARABIC:
return const Locale(ARABIC, "");
case KINYARWANDA:
return const Locale(KINYARWANDA, "");
case SWAHILLI:
return const Locale(SWAHILLI, "");
default:
return const Locale(ENGLISH, '');
}
}
then in your provider class add
Future<void> setLocale(Locale locale) async{
if(!L10n.all.contains(locale)) return;
_locale =locale;
storeLocale(locale.languageCode);//add this important
// storelocal(locale.languageCode);
notifyListeners();
}
where or widget you are implementing it e.g dropdown
Widget build(BuildContext context) {
final provider = Provider.of<LocaleProvider>(context,);
final locale = provider.locale ?? const Locale('en');
return DropdownButtonHideUnderline(
child: DropdownButton(
value: locale,
icon: const Icon(Icons.language,color:Colors.white,),
items: L10n.all.map((locale) {
final flag = L10n.getFlag(locale.languageCode);
return DropdownMenuItem(
value: locale,
onTap: ()async {
//await storeLocale(locale.languageCode);//may uncomment this
final provider =
Provider.of<LocaleProvider>(context,listen: false );
provider.setLocale(locale);
},
and in the main.dart change to stateful and override
#override
void didChangeDependencies() {
super.didChangeDependencies();
getLocale().then(
(locale) => Provider.of<LocaleProvider>(context,listen: false).setLocale(locale));
}
hope this helps
I want to search for a short sentence inside a long sentence ...
it is working fine with this demo:
String a = 'from first day i was very good';
String b = 'from first day';
print(a.contains(b));
result : true
but when I use TextField to enter a short sentence and check it if is exciting in a long sentence ...
TextField when I enter space between words doesn't show any result
Note: this app in the Arabic language and doesn't work on an android and IOS ... in English worked well in the IOS simulator but doesn't work on an android phone.
my all code:
import 'dart:convert';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:egyptian_ads_app/constant/constant.dart';
import 'package:egyptian_ads_app/pages/business_man_pages/business_man_page.dart';
import 'package:egyptian_ads_app/pages/starting_page/landing_service_page.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:share/share.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
class ItemModel {
ItemModel(
{this.id,
this.title,
this.imagePath,
this.about,
this.phoneNumber,
this.traderId,
this.type,
this.city});
int id;
String title;
String imagePath;
String about;
String phoneNumber;
int traderId;
String type;
String city;
factory ItemModel.fromJson(Map<String, dynamic> json) {
return new ItemModel(
id: json['id'],
title: json['name'],
imagePath: json["logo"]['url'],
about: json['about'],
phoneNumber: json['phone_number'],
traderId: json['trader_id'],
type: json['category']['type'],
// city: json['city'],
);
}
}
class InstantSearchPage extends StatefulWidget {
#override
_InstantSearchPageState createState() => _InstantSearchPageState();
}
class _InstantSearchPageState extends State<InstantSearchPage> {
TextEditingController _searchController = TextEditingController();
Future resultsLoaded;
List<ItemModel> _allResults = [];
List<ItemModel> _resultsList = [];
#override
void initState() {
super.initState();
_searchController.addListener(_onSearchChanged);
}
#override
void dispose() {
_searchController.removeListener(_onSearchChanged);
_searchController.dispose();
super.dispose();
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
resultsLoaded = getUserDetails();
}
getUserDetails() async {
final String url = 'https://yallservice.com/api/v1/departments';
final response = await http.get(url);
final responseJson = json.decode(response.body);
var data = responseJson['data'];
setState(() {
for (Map user in data) {
_allResults.add(ItemModel.fromJson(user));
}
});
searchResultsList();
return "complete";
}
_onSearchChanged() {
searchResultsList();
}
searchResultsList() {
List<ItemModel> showResults = [];
if (_searchController.text != "") {
for (var tripSnapshot in _allResults) {
String title = tripSnapshot.about;
print(title + title);
if (title.contains(_searchController.text)) {
showResults.add(tripSnapshot);
}
}
} else {
showResults = List.from(_allResults);
}
setState(() {
_resultsList = showResults;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: BackButton(),
title: Container(
color: Colors.white,
child: TextField(
controller: _searchController,
decoration: InputDecoration(prefixIcon: Icon(Icons.search)),
),
),
),
body: Container(
color: Colors.grey.shade300,
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: _resultsList.length,
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.white,
child: ListTile(
subtitle: Text(_resultsList[index].about),
));
// return Card(
// index: index,
// data: _resultsList,
// );
},
)),
],
),
),
);
}
}
This is due to the encoding of white spaces in RTL strings.
Try to trim the TextField text before you search for it.
Special trim method
String trim(String string) {
assert(string != null);
final stringList = string.characters.toList();
final whitespaces = ['8206', '8207', '32'];
while (whitespaces.contains(stringList.last.runes.join()))
stringList.removeLast();
while (whitespaces.contains(stringList.first.runes.join()))
stringList.remove(stringList.first);
return stringList.join();
}
Updated searchResultsList
searchResultsList() {
List<ItemModel> showResults = [];
if (_searchController.text != "") {
for (var tripSnapshot in _allResults) {
String title = tripSnapshot.about;
if (title.contains(trim(_searchController.text))) {
showResults.add(tripSnapshot);
}
}
} else {
showResults = List.from(_allResults);
}
setState(() {
_resultsList = showResults;
});
}
Ref: Text fields' values do not get trimmed correctly when textDirection: TextDirection.rtl #68093
Improvement
Your search is currently case-sensitive. Maybe you should make it case-insensitive?
searchResultsList() {
setState(() {
_resultsList = _searchController.text.isNotEmpty
? _allResults
.where((tripSnapshot) => tripSnapshot.about
.toLowerCase()
.contains(trim(_searchController.text).toLowerCase()))
.toList()
: List.from(_allResults);
});
}
I fixed the problem just by putting textDirection: TextDirection.rtl, to my TextField
I'm trying to get total number of records sqlite database table called 'persons'. After getting the total number of records I want to show this number in a Container widget inside a Text() widget. I have tried different ways to make this work but not any method I've used is working.
Below is db_helper.dart file. The funtion that needs to return total number of records is being defined as countPeople.
import 'dart:async';
import 'dart:io' as io;
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
/// models
import 'package:path/path.dart';
class DBHelper {
static Database db_instance;
Future<Database> get db async {
if (db_instance == null) {
db_instance = await initDB();
}
return db_instance;
}
initDB() async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'development.db');
var db = await openDatabase(path, version: 1, onCreate: onCreateFunc);
return db;
}
void onCreateFunc(Database db, int version) async {
// create table
await db.execute('''CREATE TABLE persons(
id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, nickname TEXT, country_id INTEGER, role TEXT, created DATETIME, updated DATETIME
);''');
}
/**
* crud functions
*/
void countPeople() async {
var db_connection = await db;
final count = Sqflite.firstIntValue(
await db_connection.rawQuery('SELECT COUNT(*) FROM persons'));
// assert(count == 2);
print('people count: $count');
}
Future<List<Person>> getAllPersons() async {
final db_connection = await db;
var response = await db_connection
.rawQuery("SELECT * FROM persons ORDER BY created DESC");
// print(response);
List<Person> list = response.map((c) => Person.fromJson(c)).toList();
return list;
}
// add new person
void addNewPerson(Person person) async {
var db_connection = await db;
String query = """
INSERT INTO persons(name,nickname,role,created,updated) VALUES('${person.name}','${person.nickname}', '${person.role}','${person.created}', '${person.updated}')
""";
await db_connection.transaction((transaction) async {
// print(query);
return await transaction.rawInsert(query);
});
}
Below is people_count.dart file. This is where I want the total record count number to be shown inside the Text() widget.
import 'package:flutter/material.dart';
import 'package:com.example.simple_app/utils/db_helper.dart';
import 'package:com.example.simple_app/models/person.dart';
import 'package:com.example.simple_app/pages/main_user_registration/create_account.dart';
class MainUserRegistration extends StatefulWidget {
MainUserRegistration({Key key}) : super(key: key);
#override
_MainUserRegistrationState createState() => _MainUserRegistrationState();
}
var dbHelper = DBHelper();
class _MainUserRegistrationState extends State<MainUserRegistration> {
var result = dbHelper.countPeople();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text('Loans'),
),
body: new Container(
child: Row(
children: <Widget>[
Text('all persons: ${dbHelper.countPeople()}'), // the total number of records should appear here
],
),
),
);
}
}
You should probably try using setState() to change async data on initState, here is what the people_count.dart would look like:
import 'package:flutter/material.dart';
import 'package:com.example.simple_app/utils/db_helper.dart';
import 'package:com.example.simple_app/models/person.dart';
import 'package:com.example.simple_app/pages/main_user_registration/create_account.dart';
class MainUserRegistration extends StatefulWidget {
MainUserRegistration({Key key}) : super(key: key);
#override
_MainUserRegistrationState createState() => _MainUserRegistrationState();
}
var dbHelper = DBHelper();
class _MainUserRegistrationState extends State<MainUserRegistration> {
int number = -1;
void countPeople() async {
int count = await dbHelper.countPeople();
setState(() => number = count);
#override
void initState() {
super.initState();
countPeople();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text('Money Lender'),
),
body: new Container(
child: Row(
children: <Widget>[
Text('all persons: ${number}'), // the total number of records should appear here
],
),
),
);
}
}
And the count people function in the db_helper.dart should return the number of people:
Future<int>countPeople() async {
var db_connection = await db;
final count = Sqflite.firstIntValue(
await db_connection.rawQuery('SELECT COUNT(*) FROM persons'));
// assert(count == 2);
print('people count: $count');
return count;
}