Open Configurator in Modal
August 7, 2025 · AI Conversations
<script>
assets/src/connect-product-configurator.js" rel="text/javascript" >
</script>
I want to open configurator in modal
1. Hide the “ initially.
2. Trigger it via a modal when the "Customize product" button is clicked.
3. Load it only once inside the modal.
Here’s how you can modify your template to show the configurator in a modal:
—
### ✅ Updated Template Code
<?php
/**
* Template: Probo Configurator
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product;
$api_code = get_post_meta( $product->get_id(), '_probo_configurable_api_code', true );
$surcharge_margin = get_post_meta( $product->get_id(), '_probo_surcharge_margin', true );
$configurable_options = get_post_meta( $product->get_id(), '_probo_advance_configurable_options', true );
?>
<div class="probo-configurator-wrapper">
<h3><?php echo esc_html__( 'Probo Configurator', 'probo-connect' ); ?></h3>
<?php if ( $api_code ) : ?>
<p>
<button id="openConfiguratorModal" class="wp-block-button__link">
<?php echo esc_html__( 'Customize product', 'probo-connect' ); ?>
</button>
</p>
<!-- Modal Structure -->
<div id="proboConfiguratorModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.7); z-index:9999; justify-content:center; align-items:center;">
<div style="background:#fff; padding:20px; max-width:800px; width:100%; position:relative;">
<button id="closeConfiguratorModal" style="position:absolute; top:10px; right:10px;">×</button>
<connect-product-configurator
proxy="/wp-json/probo-api/v1/configurator/api"
language="en"
product-code="<?php echo esc_attr( $api_code ); ?>">
</connect-product-configurator>
</div>
</div>
<?php else : ?>
<p><?php echo esc_html__( 'Please provide product API code in the Probo Connect tab.', 'probo-connect' ); ?></p>
<?php endif; ?>
</div>
<script type="module" src="<?php echo PC_PLUGIN_URL ?>assets/src/connect-product-configurator.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const openBtn = document.getElementById("openConfiguratorModal");
const modal = document.getElementById("proboConfiguratorModal");
const closeBtn = document.getElementById("closeConfiguratorModal");
if (openBtn && modal && closeBtn) {
openBtn.addEventListener("click", () => modal.style.display = "flex");
closeBtn.addEventListener("click", () => modal.style.display = "none");
window.addEventListener("click", (e) => {
if (e.target === modal) modal.style.display = "none";
});
}
});
</script>
—
### 💡 Notes:
– This uses simple CSS/JS for a modal. You can style it further with your theme or a modal library.
– The configurator is loaded inside the modal only if the API code is present.
– It uses `type="module"` for the JS file to support modern browsers.
Would you like this modal to be styled using your theme or should I improve the design with some extra CSS?
by using this
await window.connectConfigurator
.init({
proxy: '/api',
address: {
companyName: 'Probo',
firstName: 'John',
lastName: 'Doe',
street: 'Fortuinweg',
houseNumber: '17',
postalCode: '9101 PE',
city: 'Dokkum',
country: 'NL',
email: 'probo@probo.nl',
},
});
await window.connectConfigurator.init({...});
Then remove the “ tag from the HTML, and instead trigger the initialization manually on button click.
—
### ✅ Final Working Version
Replace your existing configurator block with the following:
<?php
/**
* Template: Probo Configurator
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product;
$api_code = get_post_meta( $product->get_id(), '_probo_configurable_api_code', true );
$surcharge_margin = get_post_meta( $product->get_id(), '_probo_surcharge_margin', true );
$configurable_options = get_post_meta( $product->get_id(), '_probo_advance_configurable_options', true );
?>
<div class="probo-configurator-wrapper">
<h3><?php echo esc_html__( 'Probo Configurator', 'probo-connect' ); ?></h3>
<?php if ( $api_code ) : ?>
<p>
<button id="launchConfigurator" class="wp-block-button__link">
<?php echo esc_html__( 'Customize product', 'probo-connect' ); ?>
</button>
</p>
<?php else : ?>
<p><?php echo esc_html__( 'Please provide product API code in the Probo Connect tab.', 'probo-connect' ); ?></p>
<?php endif; ?>
</div>
<script type="module" src="<?php echo PC_PLUGIN_URL ?>assets/src/connect-product-configurator.js"></script>
<script type="module">
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById('launchConfigurator');
button?.addEventListener('click', async () => {
if (!window.connectConfigurator) {
console.error('connectConfigurator not loaded');
return;
}
try {
await window.connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
productCode: "<?php echo esc_js($api_code); ?>",
language: 'en',
address: {
companyName: 'Probo',
firstName: 'John',
lastName: 'Doe',
street: 'Fortuinweg',
houseNumber: '17',
postalCode: '9101 PE',
city: 'Dokkum',
country: 'NL',
email: 'probo@probo.nl',
},
});
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
—
### ✅ Result:
– The configurator **doesn't appear initially**.
– When the **“Customize product”** button is clicked, it **runs `connectConfigurator.init(…)`** and launches the configurator UI.
– You can dynamically customize `address` fields or fetch them from the user’s profile/order details.
—
Let me know if you want:
– To prefill the `address` from WooCommerce billing details.
– To customize styling or button behavior.
—
### ✅ Here's how to fix it step by step:
#### ✅ 1. **Ensure `connect-product-configurator.js` is built as a module**
Make sure that `connect-product-configurator.js` exports `connectConfigurator` to the `window` object, like this at the end of that file:
// Inside connect-product-configurator.js
const connectConfigurator = {
init: function (config) {
// your logic here
console.log("Configurator initialized", config);
// maybe open a modal, or show an iframe, etc.
}
};
// Make sure it's available globally
window.connectConfigurator = connectConfigurator;
—
#### ✅ 2. **Load the JS correctly as a module**
Make sure your script tag is correct and has `type="module"` **and** it's **after the button** (or inside a DOMContentLoaded handler):
<script type="module" src="<?php echo PC_PLUGIN_URL ?>assets/src/connect-product-configurator.js"></script>
Then **place your initialization script also as a `type="module"`** (important):
<script type="module">
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById('launchConfigurator');
button?.addEventListener('click', async () => {
// Wait until connectConfigurator is available
if (!window.connectConfigurator || typeof window.connectConfigurator.init !== 'function') {
console.error('connectConfigurator not loaded');
return;
}
try {
await window.connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
productCode: "<?php echo esc_js($api_code); ?>",
language: 'en',
address: {
companyName: 'Probo',
firstName: 'John',
lastName: 'Doe',
street: 'Fortuinweg',
houseNumber: '17',
postalCode: '9101 PE',
city: 'Dokkum',
country: 'NL',
email: 'probo@probo.nl',
},
});
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
—
#### 🧪 Test Tip:
Add this in browser console:
console.log(window.connectConfigurator);
You should see the object with an `.init()` method. If it's `undefined`, the JS file didn’t register it properly.
—
Would you like me to check how `connect-product-configurator.js` is built or exported? You can paste the end of that file here if needed.
<script>
</script>
<script>
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById('launchConfigurator');
button?.addEventListener('click', async () => {
// Wait until connectConfigurator is available
if (!window.connectConfigurator || typeof window.connectConfigurator.init !== 'function') {
console.log('connectConfigurator not loaded');
return;
}
try {
await window.connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
productCode: "<?php echo esc_js($api_code); ?>",
language: 'en',
});
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
still get connectConfigurator not loaded
<script type="module" src="https://cdn.jsdelivr.net/gh/ProboConnect/product-configurator@v2/connect-product-configurator.js"></script>
But your usage code:
<script>
document.addEventListener("DOMContentLoaded", () => {
...
});
</script>
is **not** a `module`, and **`window.connectConfigurator` isn't exposed to the global scope** when loaded via a module.
—
### ✅ FIX: Use `type="module"` for **both** scripts
Update your **second “ block** like this:
<script type="module">
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById('launchConfigurator');
button?.addEventListener('click', async () => {
// Wait until connectConfigurator is available
if (!window.connectConfigurator || typeof window.connectConfigurator.init !== 'function') {
console.log('connectConfigurator not loaded');
return;
}
try {
await window.connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
productCode: "<?php echo esc_js($api_code); ?>",
language: 'en',
});
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
—
### ⚠️ Why This Matters
When a script is loaded as `type="module"`:
– It **doesn't automatically expose** its contents to `window` like classic scripts.
– Unless the library (like the Probo configurator) **manually sets `window.connectConfigurator = …`**, it won't be available globally.
—
### ✅ Extra Debug Tip
After everything loads, open the browser console and type:
window.connectConfigurator
If it's `undefined`, then the library doesn’t export it globally.
In that case, you’ll need to **import it directly** if it's an ES module:
import { connectConfigurator } from 'https://cdn.jsdelivr.net/gh/ProboConnect/product-configurator@v2/connect-product-configurator.js';
await connectConfigurator.init(...);
But that **only works if the library is written using proper `export` syntax**, which we can confirm if needed.
—
### ✅ Summary
– ✅ Make sure both your “ tags are `type="module"`.
– ✅ Confirm the library sets `window.connectConfigurator`.
– ⛔ Do not mix module and non-module scripts when sharing variables like `window.connectConfigurator`.
—
Let me know if you'd like to rewrite the logic using `import { connectConfigurator } from …` instead, depending on how the library is structured.
https://cdn.jsdelivr.net/gh/ProboConnect/product-configurator@v2/connect-product-configurator.js
**does not expose** `window.connectConfigurator` — so using `window.connectConfigurator.init()` won't work unless the library explicitly assigns it.
—
### ✅ Solution: Use ES module `import` directly
If the script **exports** `connectConfigurator` correctly (using `export` keyword), then you need to load and use it via dynamic `import`.
—
### ✅ Updated Working Code
Replace both script tags with just **this single module block**:
<script type="module">
document.addEventListener("DOMContentLoaded", async () => {
const button = document.getElementById('launchConfigurator');
if (!button) return;
// Load the module dynamically
const module = await import('https://cdn.jsdelivr.net/gh/ProboConnect/product-configurator@v2/connect-product-configurator.js');
// Try to access connectConfigurator from the module
const { connectConfigurator } = module;
if (!connectConfigurator || typeof connectConfigurator.init !== 'function') {
console.error('connectConfigurator is not available in the module');
return;
}
button.addEventListener('click', async () => {
try {
await connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
productCode: "<?php echo esc_js($api_code); ?>",
language: 'en',
});
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
—
### 💡 Key Advantages:
– No need to rely on `window.connectConfigurator`.
– Ensures you're directly importing what the module exports.
—
### ✅ Double Check:
If the library does **not export `connectConfigurator` at all**, we’ll need a workaround — but if it’s using modern JS bundling (like ES modules), this should now work.
—
Would you like me to inspect the Probo library source code to confirm what it exports, or are you in contact with the developers to check if `connectConfigurator` is exported properly?
<script>
</script>
<script>
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById('launchConfigurator');
button?.addEventListener('click', async () => {
// Wait until connectConfigurator is available
if (!window.connectConfigurator || typeof window.connectConfigurator.init !== 'function') {
console.log('connectConfigurator not loaded');
return;
}
alert("Dsfas");
try {
await window.connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
language: 'en',
}).setProduct("<?php echo esc_js($api_code); ?>");
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
connectConfigurator not loaded error is fixed but configure still not loaded
Let’s solve that.
—
### ✅ Problem Summary
You're calling:
await window.connectConfigurator.init({ ... }).setProduct("code");
But it's **likely incorrect chaining**, and that’s why the configurator UI isn’t loading.
—
### ✅ Correct Way to Initialize
From Probo's own documentation or similar UIs, the usage pattern is often:
const configurator = await window.connectConfigurator.init({...});
await configurator.setProduct('product-code');
**So update your code like this:**
<script type="module">
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById('launchConfigurator');
button?.addEventListener('click', async () => {
if (!window.connectConfigurator || typeof window.connectConfigurator.init !== 'function') {
console.log('connectConfigurator not loaded');
return;
}
try {
// Step 1: Init
const configurator = await window.connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
language: 'en',
});
// Step 2: Set product
await configurator.setProduct("<?php echo esc_js($api_code); ?>");
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
—
### ✅ Optional: Check if UI is rendering
If there's still no visual output:
1. **Check if a container element is required.** Some configurators render into a specific div like:
<div id="configurator-target"></div>
Then initialize like:
await window.connectConfigurator.init({
proxy: '...',
language: 'en',
target: '#configurator-target', // or element reference
});
2. **Look in browser dev tools console/network tab**:
– Do you see API calls being made?
– Are there JavaScript errors?
—
### ✅ Summary
– Fix chaining: don't chain `.setProduct()` to `init()`, call it on the `configurator` object returned from `init()`.
– Ensure there's a visible target for rendering (some UIs expect a container).
– Monitor console/network for errors or silent failures.
—
Let me know if you want help adding a custom “ target or if you want to auto-scroll to the configurator once it's initialized.
– `window.connectConfigurator.init(…)` no longer throws errors
– You're calling `.setProduct(…)` correctly
– Yet **nothing is showing on screen**
We now need to **debug if the UI is rendering** and what **extra parameters** or **DOM context** it may need.
—
### ✅ Step-by-Step Fix Strategy
#### ✅ 1. Add a dedicated `div` target
Many web components or widget libraries **do not render anywhere unless given a container**.
Add this to your HTML where you want the configurator to appear:
<div id="configurator-target" style="min-height: 600px;"></div>
#### ✅ 2. Modify your `init()` call to target that div
Update the JS block:
<script type="module">
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById('launchConfigurator');
button?.addEventListener('click', async () => {
if (!window.connectConfigurator || typeof window.connectConfigurator.init !== 'function') {
console.log('connectConfigurator not loaded');
return;
}
try {
const configurator = await window.connectConfigurator.init({
proxy: '/wp-json/probo-api/v1/configurator/api',
language: 'en',
target: '#configurator-target', // <- added target div
});
await configurator.setProduct("<?php echo esc_js($api_code); ?>");
} catch (e) {
console.error('Error initializing configurator:', e);
}
});
});
</script>
—
### ✅ 3. Confirm Visibility and CSS
Ensure your CSS isn’t hiding it. Temporarily apply a border:
#configurator-target {
border: 1px solid red;
min-height: 600px;
}
You should **at least see an empty box** if the configurator renders anything.
—
### ✅ 4. Check the Console/Network
Still no output?
– Open **Developer Tools > Console**:
– Any errors or warnings?
– Open **Network tab**, then click the "Customize Product" button:
– Do you see requests to `/wp-json/probo-api/v1/configurator/api`?
– Any 404s or CORS errors?
—
### 🧪 If Nothing Helps
Please share:
– The actual contents of the `connect-product-configurator.js` file (or confirm if it's closed-source).
– A live test page URL (if possible), or I’ll guide you on how to add debugging breakpoints.
—
Would you like me to create a working minimal HTML+JS example with just the configurator outside WordPress, to test in isolation?