Provider cannot be found above widget - flutter

class ListPosts extends StatefulWidget {
const ListPosts({Key? key}) : super(key: key);
#override
State<ListPosts> createState() => _ListPostsState();
}
class _ListPostsState extends State<ListPosts> {
#override
Widget build(BuildContext context) {
final posts = Provider.of<List<PostModel>>(context) ?? [];
return ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
title: Text(post.creator),
subtitle: Text(post.text),
);
},
);
}
}
It gives me this error on the provider and I checked everywhere but I cannot find any solution:
Error: Could not find the correct Provider<List> above this ListPosts Widget
This happens because you used a BuildContext that does not include the provider
of your choice.
I checked in other post and tutorials but could not find a good solutions, a lot of people are talking about to fix the widget tree but I believe mine is ok.

This could be your answer.
Just Follow the below code.
Your Model Class:
class PostModel {
final int id;
final int userId;
final String title;
final String body;
PostModel({this.id, this.userId, this.title, this.body});
factory PostModel.fromJson(Map<String, dynamic> json) {
return PostModel(
id: json['id'],
userId: json['userId'],
title: json['title'] ?? "",
body: json['body'] ?? "",
);
}
}
Your Provider Class:
class PostDataProvider with ChangeNotifier {
List<PostModel> post = [];
getPostData(context) async {
post = await getPostData(context); //This method will bring your posts data in formate of List<PostModel>
notifyListeners();
}
}
Your UI Screen:
class ListPosts extends StatefulWidget {
const ListPosts({Key? key}) : super(key: key);
#override
State<ListPosts> createState() => _ListPostsState();
}
class _ListPostsState extends State<ListPosts> {
#override
void initState() {
super.initState();
final postProvider = Provider.of<PostDataProvider>(context, listen: false);
postProvider.getPostData(context);
}
#override
Widget build(BuildContext context) {
List<PostModel> posts = Provider.of<PostDataProvider>(context).post;
return posts.isEmpty ? const Center(child:
CircularProgressIndicator()):ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
title: Text(post.creator),
subtitle: Text(post.text),
);
},
);
}
}

Related

Error: Could not find the correct Provider<Product> above this FeedsProduct Widget

im trying to get data that i store inside of my Product.dart module and when i tried to it give me this error
this is my feeds_product.dart file
class FeedsProduct extends StatefulWidget {
const FeedsProduct({Key? key}) : super(key: key);
#override
_FeedsProductState createState() => _FeedsProductState();
}
class _FeedsProductState extends State<FeedsProduct> {
#override
Widget build(BuildContext context) {
final productAttribute = Provider.of<Product>(context);
return InkWell(
onTap: () {
Navigator.of(context).pushNamed(ProductDetailsScreen.routeName);
},
child: Stack(
children: [
Container(
height: 300,
decoration: BoxDecoration(
border: Border.all(width: 2, color: Colors.grey),
borderRadius: BorderRadius.circular(12),
),
.
.
.
.
.......
been tried to change the code but the code only work when the final productAttribute = Provider.of<Product>(context); was gone this what it's look like in the screen right now
this is the my main.dart code
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (ctx) => ThemeNotifier()),
ChangeNotifierProvider(create: (ctx) => ProductProvider()),
],
child: Consumer<ThemeNotifier>(builder: (context, notifier, _) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const BottomNavScreen(),
routes: {
-----------------------
},
);
}),
);
}
}
this is the product.dart module code
import 'package:flutter/foundation.dart';
class Product {
final String id;
final String title;
final String description;
final double price;
final String imageUrl;
final String productCategoryName;
final String brand;
final int quantity;
final bool isFavorite;
final bool isFreeOngkir;
final bool isPopular;
Product({
required this.id,
required this.title,
required this.brand,
required this.description,
required this.imageUrl,
required this.isFavorite,
required this.isFreeOngkir,
required this.isPopular,
required this.price,
required this.productCategoryName,
required this.quantity,
});
}
class ProductProvider with ChangeNotifier {
final List<Product> _products = [...
List<Product> products() => _products;
List<Product> getByCatName(String title) {
List<Product> titleList = _products
.where((element) =>
element.productCategoryName.toLowerCase() == title.toLowerCase())
.toList();
return titleList;
}
List<Product> getByBrandName(String brandName) {
List<Product> catList = _products
.where(
(element) => element.brand.toLowerCase() == brandName.toLowerCase())
.toList();
return catList;
}
Product getById(String prodId) {
return _products.firstWhere((element) => element.id == prodId);
}
List<Product> get popularProducts {
return _products.where((element) => element.isPopular).toList();
}
}
already tried all thing that relate and search for the solution. and i watch some reference that help me but still won't work for it
You need to use ProductProvider instead of Product.
final productPorvider= Provider.of<ProductProvider>(context);

Error in Dart: The argument type 'dynamic' can't be assigned to the parameter type 'List<dynamic>'

I'm trying to integrate my RASA chatbot with a flutter app. In the response section I have the following response class but get the error "The argument type 'dynamic' can't be assigned to the parameter type 'List'". I have seen that this might be because the List could be Null but I'm explicitly checking this here, so any idea why I get this error and how to resolve it?
class RasaResponseList {
RasaResponseList(this.responses);
factory RasaResponseList.fromJson(List<dynamic> parsedJson) {
final messages = parsedJson
.map((dynamic i) => RasaResponse.fromJson(i as Map<String, dynamic>))
.toList();
return RasaResponseList(messages);
}
final List<RasaResponse> responses;
}
class RasaResponse {
RasaResponse(this.text, this.buttons);
RasaResponse.fromJson(Map<String, dynamic> json)
: text = json['text'] as String,
buttons = json['buttons'] != null ? ButtonList.fromJson(json['buttons']) : ButtonList([]);
final String text;
final ButtonList buttons;
}
The button class looks like this:
class Button {
Button({required this.title, required this.payload});
Button.fromJson(Map<String, dynamic> json)
: title = json['title'] as String,
payload = json['payload'] as String;
String title;
String payload;
}
The error message is in the line
"buttons = json['buttons'] != null ? ButtonList.fromJson(json['buttons']) : ButtonList([]);"
The class ButtonList looks like this
class ButtonList {
ButtonList(this.buttons);
factory ButtonList.fromJson(List<dynamic> parsedJson) {
final messages = parsedJson
.map((dynamic i) => Button.fromJson(i as Map<String, dynamic>))
.toList();
return ButtonList(messages);
}
final List<Button> buttons;
I added your codes but don't get any errors. I also tried parsing a dummy data in initState
import 'dart:convert';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
// TODO: implement initState
super.initState();
print(RasaResponseList(
[RasaResponse.fromJson(json.decode('{"text":"asdf", "buttons":[]}'))]));
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20),
child: SingleChildScrollView(
child: Column(children: const [
SizedBox(
height: 500,
),
TextField()
]),
)));
}
}
class RasaResponseList {
RasaResponseList(this.responses);
factory RasaResponseList.fromJson(List<dynamic> parsedJson) {
final messages = parsedJson
.map((dynamic i) => RasaResponse.fromJson(i as Map<String, dynamic>))
.toList();
return RasaResponseList(messages);
}
final List<RasaResponse> responses;
}
class RasaResponse {
RasaResponse(this.text, this.buttons);
RasaResponse.fromJson(Map<String, dynamic> json)
: text = json['text'] as String,
buttons = json['buttons'] != null
? ButtonList.fromJson(json['buttons'])
: ButtonList.fromJson([]);
final String text;
final ButtonList buttons;
}
class Button {
Button({required this.title, required this.payload});
Button.fromJson(Map<String, dynamic> json)
: title = json['title'] as String,
payload = json['payload'] as String;
String title;
String payload;
}
class ButtonList {
ButtonList(this.buttons);
factory ButtonList.fromJson(List<dynamic> parsedJson) {
final messages = parsedJson
.map((dynamic i) => Button.fromJson(i as Map<String, dynamic>))
.toList();
return ButtonList(messages);
}
final List<Button> buttons;
}

Flutter list view need to update infinite scroll pagination

I have list view with data.
i m trying to update infinite scroll pagination. But i couldnot add.
my list view
class ListData {
final int id;
final String emp_name;
final String age;
final String type;
final String joinDate;
ListData({
required this.id,
required this.emp_name,
required this.age,
required this.type,
required this.joinDate
});
static List<ListData> getList() => data.map(
(element) => ListData(
id: element['id'],
emp_name: element['emp_name'],
visa: element['age'],
type:element['type'],
expiryDate: element['joinDate'],
),
)
.toList();
}
this file return list of data's
But all the data coming in view. Need to add pagination for this. how to add infinite scroll pagination for this. Please any one can give your knowledge
Thank you
List view code
class ListingData extends StatelessWidget {
final List<ListData> emp;
const ListingData({
Key? key,required this.emp,}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: emp.length,
itemBuilder: (context, index) {
final empData = emp[index];
return ListTile(
title: Text('${empData.emp_name}'),
);
},
);
}
}
How to add pagination here Few examples are referred but not able to do me. Please give some inputs it save my day
Thank you
I'm created a demo structure for your question, which I hope could be helped
class PaginationDemo extends StatefulWidget {
const PaginationDemo({Key? key}) : super(key: key);
#override
_PaginationDemoState createState() => _PaginationDemoState();
}
class _PaginationDemoState extends State<PaginationDemo> {
final List<ListData> _rawListData = [ListData(), ListData(), ListData(), ListData()];
final List<ListData> paginatedListData = [];
bool isReachedMax = false;
int page = 0;
#override
initState() {
getListDataWithPagination();
super.initState();
}
void getListDataWithPagination() {
const int limit = 10;
final int startIndex = page * limit;
final int endIndex = startIndex + limit;
setState(
() {
final paginatedData = _rawListData.sublist(startIndex, endIndex);
if (paginatedData.isEmpty) {
isReachedMax = true;
} else {
paginatedListData.addAll(paginatedData);
page++;
}
},
);
}
#override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification.metrics.pixels == notification.metrics.maxScrollExtent) {
if (isReachedMax) return false;
getListDataWithPagination();
}
return false;
},
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return index >= paginatedListData.length
? const Center(child: CircularProgressIndicator())
: ListTile(
title: Text('${paginatedListData[index].emp_name}'),
);
},
itemCount: isReachedMax ? paginatedListData.length : paginatedListData.length + 1,
),
);
}
}

GetX UI state not changing on ListTile

I have a list of objects, but I want to change the state of one object to "isLoading" where it will have a different title, etc.
I'm building my list view:
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
body: Obx(() => buildListView(context)));
}
Widget buildListView(BuildContext context) {
return ListView.builder(
itemCount: controller.saveGames.length,
itemBuilder: (context, index) {
final saveGame = controller.saveGames.elementAt(index);
return saveGame.isLoading
? buildListTileIsLoading(context, saveGame)
: buildListTile(context, saveGame);
});
}
ListTile buildListTile(BuildContext context, SaveGame saveGame) {
return ListTile(
onTap: () => controller.process(saveGame)
);
}
The controller:
class SaveGameController extends GetxController {
final RxList<SaveGame> saveGames = <SaveGame>[].obs;
void process(SaveGame saveGame) {
saveGame.working = true;
update();
}
}
Where have I gone wrong here?
edits: Added more code
So despite the fact, I'm only updating one object in the list and not modifying the content of the list (adding/removing objects) I still need to call saveGames.refresh();
An oversight on my end didn't think you'd need to refresh the entire list if you're just changing the property on one of the objects.
Good to know :)
update() is used with GetBuilder()
obs() is used with obx()
you need to make a change on list to update widgets
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/get_navigation/get_navigation.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GetMaterialApp(
onInit: () {
Get.lazyPut(() => SaveGameController());
},
home: const HomePage(),
);
}
}
class HomePage extends GetView<SaveGameController> {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(), body: Obx(() => buildListView(context)));
}
Widget buildListView(BuildContext context) {
return ListView.builder(
itemCount: controller.saveGames.length,
itemBuilder: (context, index) {
final saveGame = controller.saveGames.elementAt(index);
return buildListTile(context, saveGame);
});
}
ListTile buildListTile(BuildContext context, SaveGame saveGame) {
return ListTile(
tileColor: saveGame.working ? Colors.red : Colors.yellow,
title: Text(saveGame.name),
onTap: () => controller.process(saveGame));
}
}
class SaveGameController extends GetxController {
final RxList<SaveGame> saveGames = <SaveGame>[
SaveGame(id: 0, name: 'a', working: false),
SaveGame(id: 1, name: 'b', working: false),
SaveGame(id: 2, name: 'c', working: false)
].obs;
void process(SaveGame saveGame) {
final index = saveGames.indexWhere((element) => element.id == saveGame.id);
saveGames
.replaceRange(index, index + 1, [saveGame.copyWith(working: true)]);
}
}
class SaveGame {
final int id;
final String name;
final bool working;
SaveGame({required this.id, required this.name, required this.working});
SaveGame copyWith({int? id, String? name, bool? working}) {
return SaveGame(
id: id ?? this.id,
name: name ?? this.name,
working: working ?? this.working);
}
}

Is there a way to rebuild AnimatedList in Flutter?

I have the following issue with my 'workout' App using multiple workoutlists with various workoutitems:
I select a workoutlist with 12 workoutitems.
The 'activity' screen with the AnimatedList is shown.
Afterwards, I select a different workoutlist with 80 workoutitems.
The AnimatedList is now showing the new workoutlist but only the first 12 workoutitems.
Why?
I thought that the AnimatedList inside the build Widget is rebuild every time (I am not using GlobalKey).
class WorkoutListView extends StatelessWidget {
const WorkoutListView({this.filename});
final String filename;
#override
Widget build(BuildContext context) {
return Selector<WorkoutListModel, List<Workout>>(
selector: (_, model) => model.filterWorkouts(filename),
builder: (context, workouts, _) {
return AnimatedWorkoutList(
list: workouts,
);
},
);
}
}
class AnimatedWorkoutList extends StatefulWidget {
const AnimatedWorkoutList({
Key key,
#required List<Workout> list,
}) : _list = list,
super(key: key);
final List<Workout> _list;
#override
_AnimatedWorkoutListState createState() => _AnimatedWorkoutListState();
}
class _AnimatedWorkoutListState extends State<AnimatedWorkoutList> {
#override
Widget build(BuildContext context) {
return AnimatedList(
initialItemCount: widget._list.length,
itemBuilder: (context, index, animation) {
final workout = widget._list[index];
return Column(
children: [
// Using AnimatedList.of(context).removeItem() for list manipulation
],
);
},
);
}
}
try this:
class AnimatedWorkoutList extends StatefulWidget {
const AnimatedWorkoutList({
#required List<Workout> list,
});
final List<Workout> list;
#override
_AnimatedWorkoutListState createState() => _AnimatedWorkoutListState();
}
class _AnimatedWorkoutListState extends State<AnimatedWorkoutList> {
#override
Widget build(BuildContext context) {
return AnimatedList(
initialItemCount: widget.list.length,
itemBuilder: (context, index, animation) {
final workout = widget.list[index];
return Column(
children: [
// Using AnimatedList.of(context).removeItem() for list manipulation
],
);
},
);
}
}