craft.js icon indicating copy to clipboard operation
craft.js copied to clipboard

Nested div tag styling by changing the settings of the component (does not work)

Open TarekFaysal opened this issue 2 years ago • 1 comments

Issue I am trying to change the styling of a component based on the settings. It works great when I apply the settings in the top level element. But If the component has sub element, it seems not to change any of it's style.

To Reproduce Here's an example code of the component:

import { Element, useNode } from '@craftjs/core';
import React from 'react';

import { AppBarSettings } from '../../../component-settings/AppBarSettings';
import { Icon } from '../elementary-components/Icon';

export const Left = ({ children }) => {
  const {
    connectors: { connect },
  } = useNode();
  return (
    <div ref={connect} className="flex flex-row justify-start space-x-2">
      {children}
    </div>
  );
};

Left.craft = {
  rules: {
    // Only accept Icon
    canMoveIn: (incomingNodes) =>
      incomingNodes.every((incomingNode) => incomingNode.data.type === Icon),
  },
};

export type AppBarProps = {
  height: number;
  backgroundColor: string;
  isLeftIconEnabled: boolean;
};
export const AppBar = ({
  backgroundColor,
  height,
  isLeftIconEnabled,
}: Partial<AppBarProps>) => {
  const {
    connectors: { connect, drag },
  } = useNode();

  return (
    <div
      className="flex flex-row items-center p-2"
      ref={(ref) => connect(drag(ref!))}
      style={{
        height: `${height}px`,
        width: '100%',
        backgroundColor: `${backgroundColor}`,
        // if I use 'isLeftIconEnabled' here to change any style, it works just fine
      }}
    >
      <div className="w-2/12">
        <Element id="left" is={Left} canvas>
          <div
            style={{
              display: isLeftIconEnabled ? 'block' : 'none',
              // if I use 'isLeftIconEnabled' here to change any style, it does not work
            }}
          >
            <Icon />
          </div>
        </Element>
      </div>
    </div>
  );
};

AppBar.craft = {
  props: {
    height: 60,
    backgroundColor: '#F4C430',
    isLeftIconEnabled: true,
  },
  related: {
    // AppBarSettings has the form to change height, background color, IsLeftIconEnabled properties
    settings: AppBarSettings,
  },
};
  • Here with 'isLeftIconEnabled', I am trying to change the styling of the nested
    component, which does not work.
  • If this is not the right way to change sub element styling, how should I proceed?
  • My end goal is to disable/enable left Icon from the "AppBar" component.
  • My environment

    Software Version(s)
    craft.js 0.2.0-beta.8
    React 18.2.0
    TypeScript 4.8.4
    Browser Chrome
    Yarn 122.19
    Operating System Windows 10

TarekFaysal avatar Jan 17 '23 11:01 TarekFaysal

When you create a linked node like what you have in your component:

 <Element id="left" is={Left} canvas>
     <div
         style={{
              display: isLeftIconEnabled ? 'block' : 'none',
              // if I use 'isLeftIconEnabled' here to change any style, it does not work
         }}
       >
        <Icon />
      </div>
</Element>

What happens is Craft looks for an existing linked node with the id left, and if it doesn't exist, it then creates the necessary Nodes for the linked node and its children (in this case the child div) node.

But once the nodes has been created, Craft will not recreate the nodes again and the only way to update the linked node and its children is via Craft's APIs:

const AppBar = () => {
  const { id } = useNode();
  const { actions, query, linkedNodes } = useEditor();
  
  useEffect(() => {
    const linkedNode = query.node(id).get().linkedNodes['left'];
  
    if ( !linkedNode ) { return; }

     // make some changes
    actions.setProp(linkedNode.id, props => {...});
  }, [actions, query]);
}

prevwong avatar Feb 11 '23 09:02 prevwong