I have a custom component with noWrap: true
and some inputs. If I use Repeat for each
in Element data bindings for this component then bind any input with data from the repeated items, those inputs won’t receive any value, logging from component props also return undefined
. I have to remove noWrap: true
or wrap the custom component inside Box
then use Repeat for each
on it to make it works.
Is this really a bug or intended?
Why do I feel like I’m being ignored?
It seems that you are encountering a limitation or possibly an unintended behavior related to the noWrap: true
option in Builder.io’s custom components. This option is designed to prevent Builder from wrapping your component in a <div>
, which can conflict with certain dynamics of data binding and repetition in Builder.io.
Background
The noWrap
option:
- When set to
true
, it instructs Builder.io not to wrap the custom component in a<div>
. - This is typically used to avoid unnecessary DOM elements, but it can interfere with how Builder.io manages bindings and contexts, especially in repeatable structures.
Analysis
Based on your description:
- Behavior with
noWrap: true
: Inputs bound to repeated data items do not receive values. - Behavior without
noWrap
or with an additional wrapper: Inputs receive values correctly.
Conclusion
While this might not strictly be a bug, it is likely a limitation stemming from how the noWrap
option interacts with Builder.io’s data binding and repetition mechanisms.
Solution
A workaround, as you’ve identified, is to use a wrapper (like a Box
component) around your custom component when working with repetition bindings. This ensures that Builder.io properly maintains the binding context.
Example Solutions:
Here are your options based on the scenario described:
Option 1: Remove noWrap: true
Consider removing the noWrap
option if it’s not strictly necessary, allowing Builder.io to manage the wrapping element itself.
Option 2: Use a Wrapper Component
Use a wrapper component, such as a Box
, to encapsulate the data-binding logic properly:
// Example without noWrap
Builder.registerComponent(Footer, {
name: 'Footer',
inputs: [
// Your input definitions here
],
});
// Usage in the Builder Visual Editor
If you need to keep noWrap: true
, wrap your custom component in a Box:
javascript
// Example with wrapped component
Builder.registerComponent(FooterWrapper, {
name: 'FooterWrapper',
inputs: [
{
name: 'items',
type: 'list',
subFields: [
{
name: 'item',
type: 'reference',
model: 'asset',
options: {
enrich: true,
includeRefs: true,
}
}
]
}
],
});
const FooterWrapper = ({ items }) => (
{items.map((item, index) => ())}
);
#### Option 3: Use Binding and Data Mapping within ComponentIf wrapping is not desirable, handle data mapping inside the component:```javascriptconst Footer = ({ items }) => { return ( Steps to Verify
- Inspect Props: Ensure that props are being passed correctly to your custom component by logging them.
- Check Bindings: Verify bindings in the builder interface. Ensure that the data structure matches your expectations.
Conclusion
While the noWrap
feature can be useful, it may cause issues with complex data binding scenarios. Using a wrapper element generally provides a robust solution to maintain binding integrity, while still achieving the desired component functionality.
For further exploration or to report this as an issue, you can reach out to Builder.io Support or check the documentation to see if there have been updates related to the handling of noWrap
in such contexts.
Thank you for your insightful reply. I’m using noWrap: true
because it makes styling my component from Visual Editor much better. I understand now this is not really a bug with Builder and I will keep an eye on the documentation to see if there is any update in the future about this issue. For now wrapping my component inside a Box is good enough.