Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,27 @@ module.exports = {
['/composition/list-of-composables', 'List of composables'],
],
},
{
title: 'Modules',
collapsable: false,
sidebarDepth: 2,
children: [
{
title: 'Catalog',
collapsable: true,
children: [
['/modules/catalog/filters', 'Filters'],
['/modules/catalog/product-types', 'Product Types'],
],
},
],
},
{
title: 'Guides',
collapsable: false,
children: [
['/guide/image-optimization', 'Image optimization'],
['/guide/override-queries', 'Override queries'],
['/guide/filters', 'Filters'],
['/guide/testing', 'Testing'],
['/guide/recaptcha', 'ReCaptcha'],
],
Expand Down
117 changes: 117 additions & 0 deletions docs/modules/catalog/filters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Filters

The category page contains filters in the sidebar. Each of these filters narrows down the list of product results and renders differently.

We introduced renderers for the most commonly used types and the mechanism to help you add and configure the filter list.

## Renderers

Before we discuss the mechanism that powers the filters list and how to configure it, let's explore the available renderers and when to use them:

- **Checkbox** for selecting multiple options from a list,
- **Radio** for selecting a single option from a list,
- **Color swatch** for displaying a list of colors and selecting multiple options,
- **Yes/No** for toggling between the `true` and `false` options.

You can find all of them in the `modules/catalog/category/components/filters/renderer` folder. The naming convention we used for these renderers is their type name followed by the `Type` keyword, e.g.: `RadioType` or `CheckboxType`.

## Configuration

Filters sidebar on the Category page is configured in the `modules/catalog/category/config/config.ts` file. It exports the `config()` function that returns an array of filter configurations. By modifying this array, you can configure filters, disable them, decide which renderers to use, etc.

Each filter can be customized using the following properties:

- `attrCode` (required) - attribute code and that must match Magento's attribute code,
- `type` (default: `checkbox`) - attribute type,
- `component` (default: `checkbox`) - component to render,
- `disabled` (default: `false`) - when set to `true` the attribute will not be displayed, nor affect the results.

Although the `type` and `component` fields might have the same values, they serve different purposes. It is best illustrated in the `yesno` renderer, whose type is `yes_no`, but the component used is `radio`. Even if renderers are the same, it's worth checking which component renders in the application.

### Examples

To change the filters, open the `modules/catalog/category/config/config.ts` configuration file and update the array returned from the `config()` function.

#### Adding new filters

To add a new filter, add a new object to the array with at least the `attrCode` property. Such configuration will generate a `checkbox` filter because this is the default value for both the `types` and `component` properties.

```diff
return [
+ {
+ attrCode: 'capacity',
+ },
// Other filters
]
```

#### Disabling filters

To disable a filter, set that filter's `disabled` property to `true`.

```diff
return [
{
attrCode: 'material',
- disabled: false,
+ disabled: true,
},
// Other filters
]
```

## GraphQL query

If you want to see or modify the way the application loads the filters, see the following files:

- `modules/catalog/category/components/filters/command/getProductFilterByCategoryCommand.ts` file for request handler,
- `modules/catalog/category/components/filters/command/getProductFilterByCategory.gql.ts` for GraphQL query.

## Adding new filter type and renderer

### Creating a new renderer

To create a new renderer, open the `modules/catalog/category/components/filters/renderer` folder and add a new file following the naming convention mentioned in the [Renderers](#renderers) section, for example `CustomType.vue`.

Every renderer must:

- Emit `selectFilter` event whenever an option is selected (type: [AggregationOption](/api-reference/magento-theme.aggregationoption.html)). Otherwise parent component will not know about the change.

```html
<input @input="$emit('selectFilter', $event.target.value)">
```

- Accept the `filter` prop (type: [Aggregation](/api-reference/magento-theme.aggregation.html))

```typescript
export default {
props: {
filter: {
type: Object as PropType<Aggregation>,
required: true
}
}
}
```

Once you have your custom renderer in place, you have to add a new renderer type to the enum located in the `modules/catalog/category/components/filters/renderer/RendererTypesEnum.ts` file.

```diff
enum RendererTypesEnum {
+ CUSTOM = 'CustomType',
// Other types
}
```

Finally, to use the new renderer, open the `modules/catalog/category/config/config.ts` configuration file and update the array returned from the `config()` function.

```diff
return [
+ {
+ attrCode: 'custom',
+ type: FilterTypeEnum.RADIO, // Value of this property might be different
+ component: RendererTypesEnum.CUSTOM,
+ }
// Other filters
]
```
73 changes: 73 additions & 0 deletions docs/modules/catalog/product-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Product Types

Magento has different types of products, and each of them requires a different way of presenting data. To address this problem, we introduced Vue components for the four most commonly used product types:

- Simple
- Grouped
- Configurable
- Bundle

These components are located in the `modules/catalog/product/components/product-types` folder.

## Product rendering

The `modules/catalog/pages/product.vue` component that powers the `/product` route dynamically switches between components based on the type of the current product.

Firstly, components for all product types are registered using dynamic imports:

```typescript
export default {
components: {
SimpleProduct: () => import('...'),
BundleProduct: () => import('...'),
ConfigurableProduct: () => import('...'),
GroupedProduct: () => import('...'),
}
}
```

Then, the `renderer` variable reads the type of the current product based on the data from Magento API (with a fallback to the `simple` type).

```typescript
const renderer = computed(() => product.value?.__typename ?? ProductTypeEnum.SIMPLE_PRODUCT);
```

Component passes this variable to the `:is` attribute of the dynamic `<component>` to switch between product components.

```html{2}
<component
:is="renderer"
v-if="product"
:product="product"
:is-fetching="loading"
@fetchProduct="fetchProduct($event.query)"
/>
```

## How to add a custom product type?

To add support for custom product types, create a new component inside the `modules/catalog/product/components/product-types` folder.

It should accept two props:

- `product` (type: [Product](http://localhost:8080/api-reference/magento-theme.product.html)) - product object fetched from the API,
- `isFetching` (type: `boolean`) - a flag indicating whether the `product.vue` components currently fetches product data .

```typescript
export default {
props: {
product: {
type: [Object, null] as PropType<Product>,
default: null,
},
isFetching: {
type: Boolean,
default: true,
},
}
};
```

Then, open the `modules/catalog/pages/product.vue` file and register the newly created component in the `components` object using dynamic import. Make sure that the name of this component matches the `__typename` value returned from the Magento API.

Once done, the page should dynamically import the component and feed it with product data.