Very fair points. I was excited by his how logic unfolds but ya - as usual I need to sleep on it and test in the real world thoroughly before I inevitably come to the conclusions you pointed out @luisherranz you buzzkill
I’m really sorry, I didn’t mean that create a client-side cart is a bad option! I actually think it’s a very good one if you have a simple cart (and thanks to @vscopise for bringing it up)
Na, you were very clear it’s an interesting method. Really valid points you added.
Wow! This article is great
I can get all products using custom post types as indicated here,
but to get all the necessary data I need to use this url,
I think I need a handler but it is not clear how to implement it.
Should I do it in frontity.settings.js
?
in index.js
?
in the component that shows products?
Thank you !!
Hi @vscopise!
I’ll recommend you to create it at the index.js
file of the theme you are using. And in case you are planning to use more than one handler you could create a separate folder or file and import them from your index.js
. It should look something similar to this:
const productsHandler = {
name: "products",
priority: 10,
pattern: "products/:slug", //Or whatever your pattern is
func: async () => {
...
};
}
const marsTheme = {
name: "@frontity/mars-theme",
roots: { ... },
state: { ... },
actions: { ... },
libraries: {
...
source: {
handlers: [productsHandler]
}
}
};
export default marsTheme;
You can take a deeper look on handlers at our documentation.
Once you’ve created the handler, if you navigate to an url with the pattern you defined (products/slug/
for example), Frontity will run the function you defined and it should store the data in the state.
After that, you just have to get that data in the component you need it, using something like this:
const Product = ({ state, actions, libraries }) => {
// Get information about the current URL.
const data = state.source.get(state.router.link);
... //Use the data as you want
}
export default connect(Product);
If you are planning to use a template just for products, you could add something like isProduct
equals true in the handler function as well, so you can filter it in your theme:
...
{
(data.isFetching && <Loading />) ||
(data.isArchive && <List />) ||
(data.isProduct && <Product />) ||
(data.isPostType && <Post />) ||
(data.is404 && <Page404 />)
}
...
Please, let us know if this helps you and if you have more questions about this we’ll be glad to help .
Hi SantosGuillamot !
I realize that there’s a problem with the endpoint
when I navigate to /product i get this message:
`
Error: post type from endpoints “posts,pages,media” with slug “product” not found
`
In Postman I can get the data:
https://wp.laotramirada.com.uy/wp-json/wp/v2/product/
in frontity.settings I have:
...
postTypes: [
{
type: 'product',
endpoint: 'product',
}
]
I’m sorry,
I realized that I was putting the wrong data in frontity.settings,
the correct way is:
...
state: {
source: {
api: "https://wp.laotramirada.com.uy/wp-json",
postTypes: [
{
type: 'product',
endpoint: 'product',
archive: 'product',
}
]
},
}
...
Should I combine a handler with postTypes to get all the necessary data?
Not sure if combining the handler with postTypes will work. I think the best option is to choose between:
- Using a custom endpoint and use a handler to point to that data.
- Using the CPT
product
and add more info (if necessary) from your WordPress.
Just to clarify it a bit more we have two cases:
If you use the CPT you defined
With that settings, you are telling Frontity to fetch that CPT. As you have defined it:
- If you access to
https://mysite.com/product/first-product
(from Frontity) you’ll be getting the info from the endpointhttps://wp.mysite.com/wp-json/wp/v2/product?slug=first-product
(from your WP). - If you access to
https://mysite.com/product
you’ll be getting a list of all your products, fetched fromhttps://wp.mysite.com/wp-json/wp/v2/product?slug=first-product
.
You could add more info to that endpoint from your WP.
If you use your own handler
We usually use handlers to fetch data from a custom endpoint, or to change the way we populate the state
.
With the handler you are telling Frontity: if we access the url https://mysite.com/products/slug
you are going to run the function defined inside it. Inside this function, we usually fetch data from a new endpoint, and how we populate the frontity.state
in order to consume that info later.
If you want to show a lists of your products when you access https://mysite.com/products
, you’d need to create a new handler to match that pattern, and fetch all the products from your endpoint.
You’d need a new handler for example if you want to point to woocommerce API instead of wp-json/wp/v2
.
In this case, if you’re fetching the data from a CPT, I guess the best option would be to use the CPT without a handler. And if you want to fetch the data from a different endpoint you may want to use a handler.
Let us know if this info helps you
Hi Mario,
If I access to /product/polo I get “is404”…
I’ve created a repo to share the code if you have time to see it
thks
I found a handler to get all data:
const homeHandler = {
name: 'home',
priority: 20,
pattern: '/',
func: async ({ route, params, state, libraries }) => {
// 1. get products data
const response = await libraries.source.api.get({
endpoint: '/wc/v3/products',
});
// 2. add product to state
const productsData = await response.json();
// 3. add route to data
Object.assign(state.source.data[route], {
productsData,
isHome: true
});
}
}
With the products in the state,
I can implement operations such as adding to the cart, generating the order, etc.
I update when I have progress
Do you have a handler for the individual products? Something like this:
const homeHandler = {
name: 'producto',
priority: 10,
pattern: '/producto/:slug',
func: async ({ route, params, state, libraries }) => {
// 1. get products data
const response = await libraries.source.api.get({
endpoint: '/wc/v3/products',
params: { slug: params.slug }
});
// 2. add product to state
const [product] = await libraries.source.populate({ state, response });
// 3. add route to data
Object.assign(state.source.data[route], {
id: product.id,
isProduct: true
});
}
}
Then access the data using:
const data = state.source.get(state.router.link);
const product = state.source.product[data.id];
Just curious. We’ve never worked with the woocommerce API
Here is the handler to get a product
const productHandler = {
name: 'product',
priority: 10,
pattern: '/product/:slug',
func: async ({ route, params, state, libraries }) => {
// 1. get product data
const response = await libraries.source.api.get({
endpoint: '/wc/v3/products',
params: { slug: params.slug}
});
// 2. add product to state
const productData = await response.json();
// 3. add route to data
Object.assign(state.source.data[route], {
productData,
isProduct: true
});
}
}
Nice!
I would like to share the code done so far to see your opinions
https://github.com/vscopise/frontity-wc
I would also like to ask you if you recommend Bootstrap, Material-UI or if you prefer another UI-framework to Frontity
Looks great so far. Thanks for sharing
I can save and get the cart from the localstorage:
const addToCart = ({ state, actions }) => ({ productId, quantity }) => {
state.theme.cart.push({ productId, quantity });
localStorage.setItem(
'frontity_wc_cart',
JSON.stringify(state.theme.cart)
);
actions.theme.calculateCartTotal();
}
...
actions: {
theme: {
afterCSR: ({ state, actions, libraries }) => {
const cachedCart = window.localStorage.getItem('frontity_wc_cart');
if (cachedCart && cachedCart.length !== 0) {
state.theme.cart = JSON.parse(cachedCart);
state.theme.cart.map(cartItem => {
//here I need to read the details of the products of the cart
//and save them in the state
});
}
}
}
How can I get the details of the products stored in the cart?