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.
-
### 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