I am having problem navigating same page and the data is not chaning in flutter - flutter

How can I navigate same page like I am tapping related products in Product details page and it will navigate to Product details page according to that related product? I want to call same page over and over again.

If you make your ProductDetails page take in a Product (or id, depends on your data) you should be able to call it. It depends on how you want to build your routes (and how you want to be able to go back), of course. Say you havce your ProductDetails take in a product to display:
ProductDetails(product: myProduct)
Then it can get the related products, and you can make the related product push another ProductDetails page:
// In your product details page
Widget relatedProductsWidget() {
return Row(
children: relatedProducts.map((product) => ProductCard(
product: product,
onTap: () => Navigator.of(context).push(
// Simply push another product on the stack
MaterialPageRoute(builder: (context) => ProductDetails(product: product))
),
)),
);
}
It depends, of course, on how you wish to go back. This way, a whole stack of ProductDetails pages will be pushed (and popped again when the back button is pressed). Alternatively, if you only want a single product details page to be present at any time, you can use Navigator.of(context).pushReplacement instead, to animate to the new location and then dispose the old route. Now when the user goes back, he is brought back to the main product list without seeing the old product first.
https://api.flutter.dev/flutter/widgets/Navigator/push.html
https://api.flutter.dev/flutter/widgets/Navigator/pushReplacement.html
I hope this gets you on the way to get your navigation sorted. If you have a specific issue, I recommend you to post a minimal version of your code to make it clear what you're trying to accomplish, as it's still a little bit vague from your question right now.

My answer only works if you use firebase.
Just complete the steps:
Create in the database a collection called products
Now add the products and in all products/documents you need to have a field called id. PS: any ids have to be used only one time.
Create in your code a global variable called id
If you tab on one of the products the id-variable need to be set to the id of the product you tabs on
In your Product-Details Page add a variable called productData
Create in your Product-Details class a method that looks like this:
getProductData() async {
await FirebaseFirestore.instance.collection("products").where("id", isEqualTo: id).get().then((value) {
productData = value.docs[0].data();
});}
In your initState() add this method:
asyncTasks() async {
await getProductData();
}
Call the method asyncTasks() in your initState
Now you can get data from the product document like this:
// Now you get the value that stands in the price field
productData["price"];
Hope it helps!

Related

Update Flutter state with GetX when the routing changes

I'm using GetX to manage the state of my Flutter app, and the structure of my pages consists of an ItemsListPage that lists some items, and an ItemDetailsPage that shows details about an specific item and lets the user change it or delete it.
I'm managing state using GetX's Reactive state management, which means that, in order to update the state of my ItemsListPage, I need to update an observable variable itemsList that is inside the ItemsListController. This variable is updated on the onInit() method of the controller, which means that whenever the controller is instantiated the list should be updated with the data fetched from the API.
The controller of the ItemsListPage looks like this:
class ItemsListController extends GetxController {
var itemsList = <AppEntity>[].obs;
#override
void onInit() {
super.onInit();
// Fetch items from the API and store them on itemsList:
getApps();
}
//...
}
And the controller of the ItemDetailsPage is like this:
class ItemsDetailsController extends GetxController {
void deleteItem() async {
final response = await deleteItem();
response.fold((failure) {
// Deal with a failure on the request
}, (response) {
if (response.success) {
// I want to update the state of the list from here
Get.toNamed('/main/');
Get.snackbar('Deleted', 'Item deleted successfully!');
}
});
}
The problem is that when the user changes or deletes an item (on the ItemDetails page), he gets redirected to the main page via Get.toNamed('/main'), and sees the old version of the list, because the onInit() method isn't called again.
Is there a way for me to trigger an action everytime the user is redirected to the ItemsList page? This would allow me to fetch the fresh data from the API and update the page. Another solution would be a way of updating the state of the ItemsListController from the ItemDetailsController, which would be even better, as it would not require another call to the back-end.
If you are using get_cli, then you can pretty much generate and use named routes along with your view, controller and bindings. But if in case you are just using the state management without binding, then this problem may occur.
The thing happening in this scenario is, your controller is building one time and then your onInit method is called, after that you do some operation on your list like deleting or adding some data, and then when you go to another screen, your controller doesn't get disposed(Strange).
You can solve this by using these ways,
Whenever you switch to another screen, let's say using Get.toNamed(route) or Get.offNamed(route) or Get.off(route), what you can do is before navigating to other screen, you can remove the controller form the memory like this,
Get.delete<ControllerName>();
In this way, your controller will be again reinstantiated when you open your screen again(Provided that you have put the Get.put(Controller()) In your widget.
If you are using named routes then you can pretty much directly use them, you don't need to do anything in order to work with them. In case you're facing the error even if you have bindings and named routes then you can perform step 1.
If you want to minimize the API calls then whenever the user deleted some item from the list, you can delete it locally and update the UI according to it. This way user won't have to see the loaders again and again.

Maintaining same state on different pages in flutter for a particular use case

I know there have been certain questions on state management in flutter, but none of them seemed to solve my use case.
Recently I was building an app based on E-commerce and encountered this real need for state management.
I had 2 pages,
One is the products page, where I add a product to the cart.
Second is the cart page, where I see products added recently to cart.
Users can add the product to the cart and then navigate to the cart. In the cart page, they can also increase or decrease the quantity of the item.
As you can see, initially yellow item was added to the cart with quantity 3, but in the cart page, user pressed the (-) button and reduced the quantity to 1. Now if the user presses the back button, then the state of the yellow product will be still 3 on the products page. Similar situation with the pink product.
Hence I tried to resolve this using normal setState and some global data structures to keep track of the quantity. But as my app grew big, its really hard to maintain the state across the pages.
I have read about different state management solutions like redux, BloC pattern, Provider, ... but I am not clear how to use any of them in my use case.
Could anyone with experience, break down the rock and help me digest?
Any sample code and explanation about how to solve this would be appreciated!
Hope my problem is clear!
ANUP SAJJAN to achieve this you can use Provider package. See these codes examples according to your case:
import 'package:flutter/material.dart';
import 'models/cartmodel.dart';
class AppState with ChangeNotifier {
List<CartModel> _cartModel = new List<CartModel>();
// Cart data list
List<CartModel> get getCart => _cartModel;
// Add item to cart
addToCart(CartModel value) {
_cartModel.add(value);
notifyListeners();
}
// Remove item to cart
removeToCart(CartModel value) {
_cartModel.remove(value);
notifyListeners();
}
}
Create an instance in main.dart:
runApp(
ChangeNotifierProvider<AppState>(
create: (_) => AppState(),
child: MyApp(),
),
)
You can now control the state :
#override
Widget build(BuildContext context) {
final appState = Provider.of<AppState>(context);
...
// manipulation
appState.getCart
appState.addToCart(value)
appState.removeToCart(value)
...
}
The state is really a vehicle to control state of one screen, not a data storage. You probably shouldn't use State in this case, but rather a database. When a user is composing their cart, you create a cart record either on the user's device SQLite, or in the cloud (Firebase?). This may seem as an overkill at first, but consider that besides having a persistent storage that you can access from anywhere, you also get user behaviour data, i.e. what they added, how they proceeded, and how many dropped off.
As for the technical side of this, in Flutter it is common to use Providers. For me, the biggest benefit is business logic encapsulation. If you don't, your specific database logic will be all over the presentation layer, and should you want to change something, you will be in trouble :)
Here is a good article regarding providers.

Flutter how to navigate back to a particular page

I have an app with multiple pages where some pages are skip depending on the user selection...
for example, I have the following page
details.dart
contact.dart
address.dart
code.dart
summary.dart
I would like to go to another page from any of the above pages...However, I want first check to see if they are in the stack and then pop to it. Otherwise push that page onto the stack
How do I do this in Flutter
I think you might want to use Navigator.of(context).pushNamedAndRemoveUntil or Navigator.popUntil.
They are very similar however like the name suggests pushNamedAndRemoveUntil pushes a new route when the predicate matches, while popUntil re-uses an existing Route/Widget in the tree.
You can read more about them on this wonderful Medium post explaining all options in greater detail.
You can use routes inside materialApp, after home
return MaterialApp(
home:... ,
routes:{
"/routeName" : (context) => PageRoute()
}
and then call route name from any pages
Ex : app in Contact page need to move to PageRoute
//Contact Page
...
onTap:(){
Navigator.pushReplacementName(context,'/routeName');
}
just use multiple Navigator.pop

How to keep history of visiting the same view in flutter?

I have a view for a book. It shows a book and a list of related books. When a user presses a related book, the app needs to display the same book view but with a different book. The requirement is that when a user hits the back button, he will see the previous book - not a previous view of a different type (e.g. search results).
I hoped to implement this use case with the standard Navigator similar to how you can register a history token in a browser while actually staying on the same page. Does anyone know if this is possible?
I tried to navigate to the same view with a different book ID:
Navigator.push(_viewContext,
MaterialPageRoute(
builder: (context) {
return BookView(id: _newBookId);
},
));
but this results in multiple copies of BookView with each one of them calling its Build at the same time. This feels like a bug to me - I would expect Navigator to take care of not creating multiple instances of the same view. The dispose() method of BookView is never called in this scenario.
I am considering keeping the "history" of book IDs in book view's state, and managing the logic of "show the previous book or pop the book view" on my own.
Am I missing something? Is there a simpler solution?
You could store the ids of the books seen by the user in a List and use WillPopScope passing to the view the id of the last book seen. So when the user clicks on the back button instead of popping the page, you return the same page but passing it the id of the previous book.

Tap on contacts name and take you to there specific page

I want to click on a contact from a list, and then be taken to that unqiue page. Its pretty much a contacts app like you have on your smartphone. So far I have a contacts list with all listed contact names and a contact information page that stores contacts data. I want to be able to click on the contacts name and it take me to a empty page that is unique to them. I will add detail to there unique page later.
I tried following some tutorials https://medium.com/#XensS/flutter-v-material-design-ii-7b0196e7b42d bu they are either outdated or elements have been changed, so it no longer works. All I want to do is be able to click persons name and it take me to a page belonging to them.
Launch the new page on onTap of your _ContactListItem.
new _ContactListItem(_contacts[index], onTap: () {
print("tapped $index");
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ContactDetailsPage()), //your new page
);
})
Refer here more information about navigation.