We’ve discussed how to use Flutter backend before. There are several options. Using a local file is certainly one of them.
In this e-commerce app, we’re going to use local files as well. As a result, what we’re displaying as products on the home page, are objects that we’ve instantiated locally.
As the first step, we have created a few products in our model folder as we’re following the model-view-controller approach.
However, we cannot go on creating like this. Right?
Therefore we need to evolve another process to add the products.
Not only that, we will also add other features, such as sign-in method, a dynamic backend where the administrator can only add, or modify products.
At present, we have a product class where we have declared the properties.
class Product {
final String id;
final String title;
final String description;
final double price;
final String imageUrl;
bool isFavorite;
Product({
required this.id,
required this.title,
required this.description,
required this.price,
required this.imageUrl,
this.isFavorite = false,
});
}
Now we can add as many items as we want.
However, we have limited ourselves to five products at present.
import 'package:flutter/material.dart';
import 'product.dart';
class Products with ChangeNotifier {
final List<Product> _items = [
Product(
id: 'p1',
title: 'Smart Phone',
description: 'A Smart Phone - get big Discount!',
price: 29.99,
imageUrl:
'https://cdn.pixabay.com/photo/2015/12/13/16/02/ios-1091302_960_720.jpg',
),
Product(
id: 'p2',
title: 'Smart TV',
description: 'A Smart TV.',
price: 59.99,
imageUrl:
'https://cdn.pixabay.com/photo/2015/02/07/20/58/tv-627876_960_720.jpg',
),
Product(
id: 'p3',
title: 'Umbrella',
description: 'Fancy and Beautiful.',
price: 19.99,
imageUrl:
'https://cdn.pixabay.com/photo/2016/11/14/03/19/umbrella-1822478_960_720.jpg',
),
Product(
id: 'p4',
title: 'Pants',
description: 'Fashionable and modern design.',
price: 99.99,
imageUrl:
'https://cdn.pixabay.com/photo/2017/03/24/19/48/jeans-2172032_960_720.jpg',
),
Product(
id: 'p5',
title: 'Shirt',
description: 'Designed with care.',
price: 47.99,
imageUrl:
'https://cdn.pixabay.com/photo/2014/08/05/10/31/waiting-410328_960_720.jpg',
),
];
List<Product> get items {
return [..._items];
}
Product findById(String id) {
return _items.firstWhere((prod) => prod.id == id);
}
void addProduct() {
// _items.add(value);
notifyListeners();
}
}
As we notice, we have used mixins to extend our class to ChangeNotifier.
The reason is simple.
We want to notify the listeners.
At present, we want to concentrate on displaying the products only.
As a result, we have a view as follows.
import 'package:flutter/material.dart';
import '../controllers/products_grid.dart';
class ProductsOverviewScreen extends StatelessWidget {
const ProductsOverviewScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('E-Commerce App'),
),
body: const ProductsGrid(),
);
}
}
Now we need to decide how to control this display. As a result, in our “controllers” folder, we have two controllers of the app.
One of the controllers will get the products according to their IDs.
And the other controller will display them on a Grid.
Flutter backend data and class constructor
We will use the GridView builder constructor to get all the products first.
Let’s see the code first.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/products.dart';
import './product_item.dart';
class ProductsGrid extends StatelessWidget {
const ProductsGrid({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final productsData = Provider.of<Products>(context);
final products = productsData.items;
return GridView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: products.length,
itemBuilder: (ctx, i) => ProductItem(
products[i].id,
products[i].title,
products[i].imageUrl,
),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
);
}
}
Through Provider we have passed the Products class where we have instantiated the product items. As a result, in the above code we can easily pass the products list using the index.
GridView builder constructor has made our life easier, as it passes the same context that Provider uses and it also passes the index of the products.
Since we have passed data through the class constructor, we can easily grab each item now.
Not only that, we can control the Material You color across the app.
![Managing the Flutter backend and controlling the color](https://i0.wp.com/sanjibsinha.com/wp-content/uploads/2022/06/Managing-the-Flutter-backend-and-controlling-the-color-.jpg?ssl=1)
Let’s take a look at the code.
import 'package:flutter/material.dart';
import '../views/product_detail_screen.dart';
class ProductItem extends StatelessWidget {
final String id;
final String title;
final String imageUrl;
const ProductItem(
this.id,
this.title,
this.imageUrl,
);
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(10),
child: GridTile(
footer: GridTileBar(
backgroundColor: Colors.yellow.shade900,
leading: IconButton(
icon: const Icon(Icons.favorite),
color: Theme.of(context).colorScheme.onSecondary,
onPressed: () {},
),
title: Text(
title,
textAlign: TextAlign.center,
),
trailing: IconButton(
icon: Icon(
Icons.shopping_cart,
color: Theme.of(context).colorScheme.onPrimary,
),
onPressed: () {},
color: Theme.of(context).colorScheme.secondary,
),
),
child: GestureDetector(
onTap: () {
Navigator.of(context).pushNamed(
ProductDetailScreen.routeName,
arguments: id,
);
},
child: Image.network(
imageUrl,
fit: BoxFit.cover,
),
),
),
);
}
}
We have got every product item property. Therefore, we can use the ID to navigate to the detail page.
That’ll be our next challenge.
We’ll discuss that topic in the next section.
Stay tuned.
Leave a Reply