Release notes
Last updated
Last updated
There is a new component and container that unifies both product base structure and base functionality - ProductContainer & Product
It is no longer required to implement the same functionally in different ways between ProductCard and ProductAction, now they both extend from Product.
Shared functionality:
Option configuration (custom, config, bundle, links, grouped)
Adding to cart
Adding to compare list
Adding to wishlist
Quantity changer
Price output
Stock output
Title, Brand, rating, samples .... renderers
Architectural changes:
No longer used variantIndex, replaced with product
to get base product or getActiveProduct
to get variant or base product. (returns base product if variant not set)
Integrated global: stock status, price and qty range.
Quantity now can be number or array - for grouped products it is array and for all other products it is number.
Customizable and bundle options are stored in enteredOptions
and selectedOptions
All added prices are stored in object adjustedPrices
(prices for bundle, custom, downloadable links, exc.), they must follow format:
Complete redesign of customizable and bundle options from scratch.
Features supported:
All BE field types are now supported ( +radio, +date, +date-time, +time )
Price updates
Validation and error messages for BE configs
Validation for product stock and quantity range
Use of UID (uid is base64 encoded value that includes key/option id/quantity)
Stores values in entered_options and selected_options
Fields are validated on event onChange
thus giving real time response
Price is updated on event onChange
thus giving real time response
Quantity changer support for all field types in bundle options
Note: "Min quantity 3!" error message indicates that product - "test-simple", requires minimum quantity of 3 to be purchased. "Field contains issues!" error message indicates that FieldGroup contains error (more info in validation and form section).
3.1 Stock
New function that calculates stock status based on passed product, no longer required different stock checks between function, now all stock status calculations are done within this function.
Function checks stock for products based on their type.
3.2. Price
New function that generates price object that should be used within project. Prices are calculated based on product type and their adjusted prices (prices that are added from links, customization, bundles, exc.).
(currently no support for tier price, meaning doesn't use tier price rule to update value based on quantity, but this feature will be added later, as its quite simple to add)
3.2.1. Updated ProductPrice component
ProductPrice now uses price gotten from getPrice()
function.
ProductPrice contains preview mode by setting property isPreview
to true
. Preview mode is the one that is visible usually on PLP, that instead of showing price, outputs "price ranges". Preview labels are now baked into ProductPrice instead of being randomly passed form different components.
Supported preview prices:
Product with tax
Product with discount
Product with tier price
Product with customizable price
Bundle product
Downloadable product
Configurable product
Out of stock
Fixed max range excl tax price (issue can be seen in image bellow for product Dynamic Bundle)
3.3. Magento Product
Function that generates Magento compatible product for graphql use.
3.4. Other functions
There are many other useful functions that are stored in Util/Product/Transform
and Util/Product/Extract
4.1. Validation utility
New utility - Validation, that can be used for both property checks and DOM object checks, thus removing previously limited validation that was directly added only in fields and forms.
4.1.1. Validation rule structure:
!!! All rule fields are optional (AKA not required) !!!
4.1.2. Globalized error messages:
If there is no custom error message provided, then default error message for specific validation type will be outputted.
Util/Validator/Config.js
Note: In the newest version, input type validation is not performed if the value is empty, so it will output in this case only the message "This field is required!", but image still works as example to show multiple error msg output.
4.1.3. Validation functions:
There are two validation functions:
Value validation
DOM validation, if passed rule then will check both children objects and itself if rule is not passed then checks only children.
4.2. Form, Fields, FieldGroup, FieldForm
Complete redesign of Forms, Fields, FieldForm.
New features:
Forms code now is simpler, smaller, faster and more extendable.
Fields and Field groups contain now validation
event
New component Field Group
Integrated support for new Validation Utility
Stateless by default (reduces render count on update)
Support of all field types
For field type file
- outputs plural type messages if contains attr multi, otherwise uses singular form.
Fields can output "*" next to label if parameter addRequiredTag
is set to true.
Form onSubmit
passes form and fields to passed functions onSubmit
and onError
ether in object mode or in array mode (depends on parameter returnAsObject
) :
Field code example:
As fields and forms are now stateless by default, to set default values requires to pass attributes defaultValue
or defaultChecked
Field group example:
Field Groups are containers for fields, their use case is quite simple:
Field group passes validation only if all its fields are valid and if rules applied to it self are valid
Field group validation rule isRequired is used to ensure that at least one field contains value. (Example: you have 4 checkboxes, to submit form you need at-least one of them to be selected, to do that you would wrap those checkboxes in FieldGroup add add isRequired rule in validations, similarly if required at-least two checkboxes you can wrap them in FieldGroup and add match rule in validation)
All components are updated to use new forms and fields
4.3. FieldForm
Architectural changes are made for FieldForm
component, it now utilizes new syntax for fields and supports multilayered sectioning via FieldGroup
component:
Example of new fieldMap:
Now field map returns array instead of object.
If object contains parameter fields
then it will render FieldGroup.
Notice that fields
can contain both objects for fields and for field groups, thus allowing to create complex structures with undefined depth.
Form parameters are assigned from function getFormProps
, by default it will return ...this.props
.
Note: FieldForm form structures are moved out to files called [form-name].form.js
, to reduce size of main component, and make forms more readable + we can utilize function caching for that.
Note for me (not in this PR): Add possibility off accessing values in same group/form when doing validation & attribute setting in fields themself AKA make fields in same group aware of other fields. Example: when setting isDisabled, I want option to access different field values without storing them in separate parameter, as it was done before.... so it would look something like this isDisabled: ({ [differentFieldName]: { value } }) β value && value.length > 10
5.1. Updated downloadable, grouped components
Downloadable and Grouped options are updated to use new Product.container and new Form
5.1.1. Grouped product
If grouped product contains product with tier prices it will also output them (same as in Magento):
Images no longer show 'Image no specified' (check image above - kept as example):
Images use correct thumbnail source, instead of wrong one that outputted large images. (I guess small images where previously loaded)
FE validation for quantity and stock:
5.2. Commenting
All new code contains functional, class and attribute comments.
New code also includes region comments //#region
, to increase readability in IDE (in imagge bellow GETTERS & EVENTS are collapsed).
5.3. Naming
All new code follows naming schema that on attribute destruction converts snake_case
to camelCase
Example
5.4. Function caching
Added utility to cache functions based on their input, to improve performance on functions with larger complexity.
Functions can be cached in two modes:
Global - all components that call function will store value-response pairs in shared space
Local - component will cache its function value-response pair in separated space. ( In development... currently not priority )
Note: When using this function args
should be as specific as possible, because key is generated from JSON.stringify(args)
(example: instead of passing whole product object, pass fields that are required, for example price_range)
5.5. Deprecated saveCartItem mutation
No longer used mutation saveCartItem
instead now we are using Magento native graphql mutation addProductsToCart
and updateCartItems
Currently only saveCartItem is migrated to native graphql mutation, thus there are two request made while saving cart item - first one for adding products, second one to get updated cart. This will be changed in graphql update commit.
scandipwa/quote-graphql also contains patch for addProductsToCart
to solve Magento issue for multiple checkbox selection for bundle bundles. (Example: Product2 options)
also added file upload support by passing (code bellow) into value field:
5.6. Deprecated saveWishlistItem mutation
No longer used mutation saveWishlistItem
instead now we are using Magento native graphql mutation addProductsToWishlist
Currently only saveWishlistItem is migrated to native graphql mutation, thus there are two request made while adding item - first one for adding products, second one to get updated wishlist. This will be changed in graphql update commit.
5.7. Configs
Few configurations are combined into object based configuration.
Example:
Reason:
Reduces import count
Simpler to read and remember
IDE will output all options when accessing object
You can use PropTypes.oneOf(Object.values(CONFIG))
in props
and in other places.
5.8. Other
Cart item options outputted based on their type
Quantity changer is disabled for out of stock product:
In PLP if product out of stock Add to cart button is in disabled state, if product in stock and requires configuration (customizable, config, bundle, download links) outputs Configure
button if product in stock and doesn't require any changes, then outputs add to cart button.
If parent is set as Out of stock, then active variant will also show out of stock (same as Magento) + options will be shown as disabledof