Custom scripts
You can use custom scripts to customize the module behaviour.
You can create javascript files in these folders:
/js/dynamic(create thedynamicfolder if it doesn't exist)/themes/[current theme]/assets/js/dynamic
The file name should be:
custom.js(if you want to target all products)customX.js(if you want to only target the product with ID=X)
For example, if you want to target product#10, you can create a file namedcustom10.js
Detecting when the module is loaded
Since the module loading is deferred, you need to listen for the dp.load event in order to execute your custom script correctly and avoid errors.
document.addEventListener("dp.load", function() {
// Your code here
});Updating the properties of a field
You can change a field properties from the custom script, for that you need to use the updateField function.
Code example:
window.dp.methods.updateField(field_name, props);
// This example will change the value of the width field as well as the min, max and step properties
window.dp.methods.updateField("width", {
value: 50,
min: 10,
max: 100,
step: 10
});The props object can have these items
// The props interface has this shape
export interface IFieldSettings {
value: string | number;
value_formatted: string;
min: number;
max: number;
step: number;
required: number;
max_size: number;
min_date: string;
max_date: string;
multiselect: boolean;
display_value_price: number;
display_secondary_value_price: number;
display_in_popup: number;
}Some field types display the value_formatted property, such as the price field.
To update it, you can use this code for example
window.dp.methods.updateField("price_field", {
value: 50,
value_formatted: '50€'
});Get a field properties
You can use the getField function to get the properties of a field.
window.dp.methods.getField(field_name);
var props = window.dp.methods.getField("width");The value of props will have this shape
{
active: 1
common: 0
description: ""
dir: "/dynamicproduct/images/field"
ext: ".jpg"
favorite: 0
force_id: false
id: 66
id_group: "0"
id_product: 11
id_unit: 0
image_url: null
init: 0
label: "Width"
linked: "0"
name: "width"
options: []
position: "2"
settings: {
color: null
dir: null
display_in_popup: null
display_secondary_value_price: null
display_value_price: null
ext: ".jpg"
extensions: null
extra: null
force_id: false
hide_when_empty: 1
id: null
id_field: 66
id_unit: null
init: null
max: null
max_date: null
max_size: null
min: null
min_date: null
min_height: null
min_width: null
multiselect: null
position: null
price_unit: null
required: null
show_in_summary: 0
step: 1
thumb_suffix: "-thumb.jpg"
}
thumb_suffix: "-thumb.jpg"
thumb_url: null
type: 1
unit: {
dir: null
displayed: 1
ext: ".jpg"
force_id: false
id: null
name: null
position: null
symbol: null
thumb_suffix: "-thumb.jpg"
}
value: ""
}Detecting a calculation result
You can subscribe to the module stores in order to detect the calculation results.
The module uses Vegemite stores under the hood.
Code example:
document.addEventListener('dp.load', function() {
window.dp.stores.calculator.listen(function(data) {
console.log(data);
});
});The data will have this shape
{
customization_prices: {
price_ht: 10
price_ht_nr: 10
price_ttc: 12
price_ttc_nr: 12
}
debug_messages: null
final_prices: {
price_ht: 20
price_ht_nr: 20
price_ttc: 24
price_ttc_nr: 24
}
formatted_prices: {
price_ht: "€20.00"
price_ht_nr: "€20.00"
price_ttc: "€24.00"
price_ttc_nr: "€24.00"
}
formatted_unit_prices: {
price_ht: "€20.00"
price_ht_nr: "€20.00"
price_ttc: "€24.00"
price_ttc_nr: "€24.00"
}
input_fields: {
width: {
dir: null
ext: ".jpg"
field: {
// information about the field, similar to the value returned by getField
}
force_id: false
id: null
id_field: 66
id_input: 0
id_shop_list: []
image_url: null
label: "Width"
name: "width"
options: "[]"
position: null
secondary_value: "0"
selected_options: []
thumb_suffix: "-thumb.jpg"
thumb_url: null
type: 1
value: 0
value_formatted: 0
visible: 1
}
}
met_conditions: []
oos: false
success: 1
unit_prices: {
price_ht: 20, price_ht_nr
:
20, price_ttc
:
24, price_ttc_nr
:
24
}
use_tax: true
visibility: {
groups: []
}
weight: 0
weight_formatted: "0 kg"
}Detecting any change on fields
You can subscribe to the fields store to detect any change on the fields.
The result will be an object containing each field Example code
document.addEventListener('dp.load', function() {
window.dp.stores.fields.listen(function(fields) {
console.log(fields);
});
});The fields variable will have this shape
{
width: {
dir: null
ext: ".jpg"
field: {
// information about the field, similar to the value returned by getField
}
force_id: false
id: null
id_field: 0
id_input: 0
id_shop_list: []
image_url: null
label: null
name: "changed"
options: ""
position: null
secondary_value: "0"
selected_options: ""
thumb_suffix: "-thumb.jpg"
thumb_url: null
type: 4
value: "width"
value_formatted: "width"
visible: 0
}
,
height: {
// same shape as the width field
}
,
// ...
}Validating the fields
If you need to validate the fields programmatically, you can use the validateFields function.
Example code:
var valid = window.dp.methods.validateFields();
// valid will be either true or contain error messages based on the validity of the fields
// The module will highlight errors and will scroll to the first visible errorAdd the customization to cart
If you need to add the customization to cart, then you can use the addToCart function.
Example code
window.dp.methods.addToCart().then(function(response) {
// response is either true or false based on the success of the operation
});Customizing the module selectors
Since many themes have a different structure than the default one, the module allows you to change the selectors used to target the product page elements and to better position the module within the page.
Here's the default selectors structure:
export type DynamicProductProps = {
// used to position the module within the page
hook: (container: HTMLDivElement) => void;
// used to position the layers container within the preview images
preview_hook: (layers_container: HTMLDivElement) => void;
selectors: {
price: string; // price with discount (if applicable)
regular_price: string; // price without discount
qty_input: string; // the quantity input
form: string; // the product form
};
};Here are the default values:
window.dp = {
hook(container: HTMLDivElement) {
const product_actions = document.querySelector('.js-product-actions');
product_actions?.prepend(container);
},
preview_hook(layers_container: HTMLDivElement) {
const images_container = document.querySelector('.js-images-container');
images_container?.prepend(layers_container);
},
selectors: {
price: '.current-price-value',
regular_price: '.regular-price',
qty_input: '#quantity_wanted',
form: '#add-to-cart-or-refresh'
}
};To change the hook, you can use this code for example:
window.dp.hook = function(container) {
const product_actions = document.querySelector('.js-product-actions');
product_actions?.append(container);
};To change a selector, you can use this code for example:
window.dp.selectors.price = '.product-price > span';TIP
You can also use the custom hook in your theme tpl.
Custom fields
Check how to create custom fields here
