Reputation: 53
I want to search from the search button, but it doesn't work. I'm missing a small place, but I couldn't find it.
my code dataTable
import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:novadan_admin/global/models/endpoint/responsedata/nv_search_products_response_data.dart';
import 'package:novadan_admin/global/utilities/consts_design.dart';
import 'package:novadan_admin/global/widgets/datatable/global_paginated_datatable.dart';
import 'package:novadan_admin/global/widgets/loading_indicator.dart';
import 'package:novadan_admin/modules/products/products_main/controllers/products_main_controller.dart';
import 'package:novadan_admin/modules/products/products_main/widgets/datatable/datasource.dart';
import 'package:novadan_admin/modules/products/products_main/widgets/datatable/widgets/head/head.dart';
import 'package:novadan_admin/modules/products/products_main/widgets/datatable/widgets/header/actions.dart';
class ProductsMainDataTable extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(defaultPadding),
decoration: BoxDecoration(
color: secondaryColor,
borderRadius: defaultRadius,
),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
ProductsMainDataTableHead(),
SizedBox(
height: 30,
),
GetBuilder<ProductsMainController>(
id: "datatable",
builder: (controller) {
return FutureBuilder(
future: controller.mainFuture.value,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
case ConnectionState.waiting:
return SizedBox(height: 600, child: LoadingIndicator());
case ConnectionState.done:
if (snapshot.hasError) {
return SizedBox(
width: double.infinity,
height: 600,
child: Center(
child: SelectableText(snapshot.error.toString(), style: Theme.of(context).textTheme.caption)));
}
controller.productsData.value = (snapshot.data! as List)[0];
final DataTableSource _data = ProductsMainSource(controller.productsData.value.searchProductsData!);
return SizedBox(
width: double.infinity,
height: (controller.productsData.value.searchProductsData!.length * 120) + 200,
child: GlobalPaginatedDataTable(
source: _data,
minWidth: 600,
emptyText: "productsmainnotfound",
rowsPerPage: controller.productsData.value.searchProductsData!.length == 0
? 1
: controller.productsData.value.searchProductsData!.length,
dataRowHeight: 120,
showCheckboxColumn: true,
headerAction: ProductsMainDataTableHeaderActions(),
statusMessage: controller.statusMessage.value,
hintText: "",
/* "${controller.page.value}-${(controller.productsData.value.total! controller.productsData.value.perPage!).toStringAsFixed(0)}",
pageLength: (controller.productsData.value.total! /
controller.productsData.value.perPage!)
.round(),
onFirst: () => controller.getFirstPage(),
onLast: () => controller.getLastPage(),
onPrevious: () => controller.getPreviousPage(),
onNext: () => controller.getNextPage(),
onPage: (value) => controller.getPage(value!), */
columns: [
DataColumn2(
size: ColumnSize.S,
label: Text(
"productsmainpicture".tr,
style: Theme.of(context).textTheme.subtitle1,
),
),
DataColumn2(
size: ColumnSize.L,
label: Text(
"productsmaintitletext".tr,
style: Theme.of(context).textTheme.subtitle1,
),
),
DataColumn2(
size: ColumnSize.S,
label: Text("productsmainprice".tr, style: Theme.of(context).textTheme.subtitle1),
),
DataColumn2(
size: ColumnSize.S,
label: Text("productsmainaction".tr, style: Theme.of(context).textTheme.subtitle1))
],
));
default:
return SizedBox(height: 600, child: LoadingIndicator());
}
});
}),
]));
}
}
My code ProductsMainController
import 'dart:async';
import 'package:get/get.dart';
import 'package:novadan_admin/global/models/endpoint/responsedata/nv_search_products_response_data.dart';
import '../services/products_main_service.dart';
class ProductsMainController extends GetxController {
final productsData = NvSearchProductsResponseData().obs;
final mainFuture = Future.wait([]).obs;
final productsFuture = Future.value(NvSearchProductsResponseData()).obs;
var perPage = "50".obs;
var page = 1.obs;
var statusMessage = "".obs;
@override
void onInit() {
super.onInit();
getProducts();
mainFuture.value = Future.wait([productsFuture.value]);
}
getProducts() {
productsFuture.value = searchProducts("");
}
getSearchedProducts(String searchText) {
productsFuture.value = searchProducts(searchText);
update(["datatable"]);
}
selectRow(bool selected, index) {
productsData.value.searchProductsData![index].selected = selected;
update();
}
void getFirstPage() {
if (page.value != 1) {
page.value = 1;
getProducts();
update();
}
}
void getLastPage() {
getProducts();
update();
}
void getPreviousPage() {
if (page.value != 1) {
page.value -= 1;
getProducts();
update();
}
}
void getNextPage() {
getProducts();
update();
}
void getPage(int newPage) {
page.value = newPage;
getProducts();
update();
}
}
data is not coming
Upvotes: 0
Views: 113
Reputation: 199
I have made my custom Search Widget to do filtering. Check out these codes.
Main Page:
import 'package:flutter/material.dart';
import "package:inventory_control_flutter/models/stock.dart";
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:inventory_control_flutter/templates/stock_card.dart';
import 'package:inventory_control_flutter/widgets/search_widget.dart';
class StockList extends StatefulWidget {
const StockList({Key? key}) : super(key: key);
@override
_StockListState createState() => _StockListState();
}
class _StockListState extends State<StockList> {
String query = '';
List<Stock> arrStock = [];
List<Stock> arrFilteredStock = [];
bool isFiltered = false;
Future<List<Stock>> _fetchData() async {
if(!isFiltered){
final response = await http
.get(Uri.parse('http://tos.petra.ac.id/~c14170010/api/getAllItem.php'));
if (response.statusCode == 200) {
var jsonData = json.decode(response.body);
List<Stock> arr = [];
for (var data in jsonData) {
Stock stock = Stock(data["item_id"], data["code"], data["comname"],
data["unit"], data["quantity"]);
arr.add(stock);
}
arrStock = arr;
arrFilteredStock = arrStock;
} else {
throw Exception('Failed to load stock');
}
}
return arrFilteredStock;
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
FocusManager.instance.primaryFocus?.unfocus();
},
child: SafeArea(child:
Scaffold(
body: Column(children: <Widget>[
Container(
width: double.infinity,
margin: EdgeInsets.all(16),
child: const Text("Inventory",
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: "Quicksand",
fontSize: 20,
fontWeight: FontWeight.w700)),
),
Container(
child:_buildSearch(),
),
Flexible(
child:
FutureBuilder(
future: _fetchData(),
builder: (context, AsyncSnapshot snapshot) {
if(isFiltered){
isFiltered = false;
return ListView.builder(
// itemCount: snapshot.data.length,
itemCount: arrFilteredStock.length,
itemBuilder: (context, index) {
var id = arrFilteredStock[index].id;
var code = arrFilteredStock[index].itemCode;
var comname = arrFilteredStock[index].itemComname;
var unit = arrFilteredStock[index].itemUnit;
var qty = arrFilteredStock[index].itemStockBalanceQty;
return StockCard(
stock: Stock(id, code, comname, unit, qty));
},
);
}else{
if (snapshot.data == null) {
return Container(
child: const Center(
child: Text("Loading..."),
));
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var id = snapshot.data[index].id;
var code = snapshot.data[index].itemCode;
var comname = snapshot.data[index].itemComname;
var unit = snapshot.data[index].itemUnit;
var qty = snapshot.data[index].itemStockBalanceQty;
return StockCard(
stock: Stock(id, code, comname, unit, qty));
},
);
}
}
}),
)
]))
),
);
}
void searchItem(String query){
final items = arrStock.where((item){
final nameLower = item.itemComname.toLowerCase();
final codeLower = item.itemCode.toLowerCase();
final searchLower = query.toLowerCase();
return nameLower.contains(searchLower) || codeLower.contains(searchLower);
}).toList();
isFiltered = true;
if(query.isEmpty){
isFiltered = false;
}
setState(() {
this.query = query;
this.arrFilteredStock = items;
});
}
Widget _buildSearch() => SearchWidget(
text: query,
hintText: "Item Code or Item Name",
onChanged: searchItem,
);
}
Custom Search Widget:
import 'package:flutter/material.dart';
class SearchWidget extends StatefulWidget {
final String text;
final ValueChanged<String> onChanged;
final String hintText;
const SearchWidget({
Key? key,
required this.text,
required this.onChanged,
required this.hintText,
}) : super(key: key);
@override
_SearchWidgetState createState() => _SearchWidgetState();
}
class _SearchWidgetState extends State<SearchWidget> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
final styleActive = TextStyle(color: Colors.black);
final styleHint = TextStyle(color: Colors.black54);
final style = widget.text.isEmpty ? styleHint : styleActive;
return Container(
height: 42,
margin: const EdgeInsets.fromLTRB(16, 16, 16, 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
border: Border.all(color: Colors.black26),
),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: TextField(
controller: controller,
decoration: InputDecoration(
icon: Icon(Icons.search, color: style.color),
suffixIcon: widget.text.isNotEmpty
? GestureDetector(
child: Icon(Icons.close, color: style.color),
onTap: () {
controller.clear();
widget.onChanged('');
FocusScope.of(context).requestFocus(FocusNode());
},
)
: null,
hintText: widget.hintText,
hintStyle: style,
border: InputBorder.none,
),
style: style,
onChanged: widget.onChanged,
),
);
}
}
Upvotes: 1