Custom Component with noWrap "true" cause focus issue

I add the custom react component and setup the meta noWrap “true”.
When i edit the page, the custom component can not be selected if this attribute setup. ( i can just use the layer to focus this component. )

Hi @frank.hsu - you need to be sure to forward props.attributes attributes to your noWrap component in order for it to be selectable. Builder passes things down like props.attributes.className that must be included for selecting and editing to work, like below:

import { TextField } from '@material-ui/core'

export const BuilderTextField = props => (
  // Important: Builder.io must add a couple classes and attributes via props.attributes
  // Important: If you add your own classes do it after ...props.attributes 
  <TextField 
    variant={props.variant} 
    {...props.attributes} 
    className={`my-class ${props.attributes.className}`}
   />
)

Builder.registerComponent(BuilderTextField, {
  name: 'TextField',
  noWrap: true, // Important!
  inputs: [{ name: 'variant', type: 'string' }]
})

thks, it works after pass the attributes.

Hi steve, thank you for you detailed answer.
Im having trouble passing the “builder-id” to my custom component. I tried your solution of passing {...props.attributes} and it does pass the class names but the builder-id attribute is filtered out for some reason.

Im using next.js and my custom component is a styled component. I fear next.js filters it.
Do you have an idea how to pass the builder-id attribute to the component without it being filtered?

export const BuilderTextField = props => (
  // Important: Builder.io must add a couple classes and attributes via props.attributes
  // Important: If you add your own classes do it after ...props.attributes 
  <TextField 
    variant={props.variant} 
    {...props.attributes}  // 'builder-id' exists in props.attributes but is filtered out and isn't present in the DOM
    className={`my-class ${props.attributes.className}`}
   />
)

Builder.registerComponent(BuilderTextField, {
  name: 'TextField',
  noWrap: true, // Important!
  inputs: [{ name: 'variant', type: 'string' }]
})

This solution works well for my problem:

    <Component
      {...props}
      {...props.attributes}
      ref={
        (el: HTMLElement | null) => {
          attributes &&
          Object.entries(attributes).forEach(([attributeName, attributeValue]) => {
            if (attributeName.startsWith("builder-")) {
              el?.setAttribute(attributeName, attributeValue as string); // Here i set the "builder-*" attributes on the element
            }
          });
        }
      }
    >
      {children}
    </Component>
1 Like

adding {…props.attributes} seems to defeat the purpose of the noWrap option. I just get it wrapped again. I need to get rid of the ability of editors to override my CSS with the inline builder styles

Hello @Brent9997,

To get rid of default editor styles, you can possibly disable Use default styles from Settings → Advanced Settings → Editor

const ButtonTwilio = (props) => {
  const ref = React.useRef();

  return (
    <Button
      ref={(el: HTMLElement | null) => {
        console.log("el", props.attributes);
        el?.attributes &&
          Object.entries(props?.attributes).forEach(
            ([attributeName, attributeValue]) => {
              if (attributeName !== "className") {
                el?.setAttribute(attributeName, attributeValue as string);
              } 
            }
          );
      }}
      variant={props.variant}
      size={props.size}
    >
      {props.children}
    </Button>
  );
};