Replies: 2 comments
-
Add editable: true to Components: Ensure each element in your product card (like the title, price, description) has editable: true set, so GrapesJS knows they can be edited. Set draggable: true and selectable: true on Product Cards: This will allow you to select and move product cards within the editor. Ensure data-gjs-type Attributes Are Set: Adding data-gjs-type attributes is essential for GrapesJS to treat these as components. |
Beta Was this translation helpful? Give feedback.
-
Here’s an update to make product cards editable and selectable in the GrapesJS canvas. Solution: Enable Product Cards as Editable ComponentsThis solution ensures each product card is editable, selectable, and draggable within the editor. products.forEach(product => {
const productCard = document.createElement('div');
productCard.className = `${pfx}-card`;
productCard.setAttribute('data-gjs-type', 'product-card');
productCard.setAttribute('data-gjs-editable', 'true');
productCard.setAttribute('data-gjs-draggable', 'true');
productCard.setAttribute('data-gjs-selectable', 'true');
const imageContainer = document.createElement('div');
imageContainer.className = `${pfx}-image-container`;
imageContainer.setAttribute('data-gjs-type', 'image-container');
const img = document.createElement('img');
img.src = product.image;
img.alt = product.title;
img.className = `${pfx}-image`;
img.setAttribute('data-gjs-type', 'image');
img.setAttribute('data-gjs-editable', 'false'); // Images are typically not editable
const cardContent = document.createElement('div');
cardContent.className = `${pfx}-card-content`;
cardContent.setAttribute('data-gjs-type', 'card-content');
const title = document.createElement('h3');
title.className = `${pfx}-title`;
title.textContent = product.title;
title.setAttribute('data-gjs-type', 'text');
title.setAttribute('data-gjs-editable', 'true');
const price = document.createElement('p');
price.className = `${pfx}-price`;
price.textContent = '$' + product.price.toFixed(2);
price.setAttribute('data-gjs-type', 'text');
price.setAttribute('data-gjs-editable', 'true');
// Add other components similarly with editable attributes...
productCard.appendChild(imageContainer);
productCard.appendChild(cardContent);
productsContainer.appendChild(productCard);
}); |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
### HELP WANTED
Here is my custom plugin for productlisting but the product card not editable, selectable in canvas
but listing working properly
@mohamedsalem401 can please we have discussion what went wrong
`
// @ts-ignore
import type { Plugin, BlockProperties, ComponentDefinition } from 'grapesjs';
export type PluginOptions = {
id?: string;
label?: string;
block?: Partial;
props?: ComponentDefinition;
apiEndpoint?: string;
classPrefix?: string;
};
const topProductsPlugin: Plugin = (editor, opts = {}) => {
const options: PluginOptions = {
id: 'top-products',
label: 'Top Products',
block: {},
props: {},
apiEndpoint: 'https://fakestoreapi.com/products',
classPrefix: 'top-products',
...opts,
};
const { block, props } = options;
const id = options.id!;
const label = options.label!;
const pfx = options.classPrefix!;
// Add block
editor.BlockManager.add(id, {
media: '',
label,
category: 'Extra',
content: {
type: id,
},
...block
});
const scriptStr = `
const fetchProducts = async function() {
const el = this;
const productsContainer = el.querySelector('[data-js=products-container]');
const loadingEl = el.querySelector('[data-js=products-loading]');
const errorEl = el.querySelector('[data-js=products-error]');
};
// Initialize products
fetchProducts.call(this);
// Add refresh functionality
const refreshBtn = this.querySelector('[data-js=products-refresh]');
if (refreshBtn) {
refreshBtn.addEventListener('click', () => {
fetchProducts.call(this);
});
}
`;
editor.Components.addType(id, {
model: {
defaults: {
name: label,
classes: [pfx],
droppable: false,
script: scriptStr,
components:
<div class="${pfx}-container"> <div class="${pfx}-header"> <h2 class="${pfx}-section-title">Top my Products</h2> <button data-js="products-refresh" class="${pfx}-refresh"> Refresh Products </button> </div> <div data-js="products-loading" class="${pfx}-loading">Loading products...</div> <div data-js="products-error" class="${pfx}-error" style="display: none;"></div> <div data-js="products-container" class="${pfx}-grid" style="display: none;"></div> </div>
,styles:
.${pfx}-container { padding: 20px; max-width: 1200px; margin: 0 auto; } .${pfx}-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .${pfx}-section-title { font-size: 1.8rem; color: #333; margin: 0; } .${pfx}-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; padding: 20px 0; } .${pfx}-card { border: 1px solid #eee; border-radius: 8px; overflow: hidden; transition: transform 0.3s ease, box-shadow 0.3s ease; background: white; } .${pfx}-card:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0,0,0,0.1); } .${pfx}-image-container { height: 200px; overflow: hidden; padding: 20px; background: #f8f9fa; } .${pfx}-image { width: 100%; height: 100%; object-fit: contain; } .${pfx}-card-content { padding: 15px; } .${pfx}-title { font-size: 1rem; margin: 0 0 10px 0; color: #333; line-height: 1.4; } .${pfx}-price { font-size: 1.2rem; font-weight: bold; color: #e74c3c; margin: 10px 0; } .${pfx}-rating { display: flex; align-items: center; gap: 5px; margin: 10px 0; } .${pfx}-stars { color: #f1c40f; } .${pfx}-count { color: #666; font-size: 0.9rem; } .${pfx}-category { color: #666; font-size: 0.9rem; text-transform: capitalize; margin: 5px 0; } .${pfx}-description { font-size: 0.9rem; color: #666; line-height: 1.4; margin: 10px 0 0 0; } .${pfx}-loading, .${pfx}-error { padding: 40px; text-align: center; color: #666; font-size: 1rem; display: flex; justify-content: center; align-items: center; } .${pfx}-error { color: #dc3545; } .${pfx}-refresh { background: #007bff; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; transition: background 0.3s ease; } .${pfx}-refresh:hover { background: #0056b3; }
,...props,
},
},
});
};
export default topProductsPlugin;`
Beta Was this translation helpful? Give feedback.
All reactions