이전 시간에 저는 특정한 버튼을 누르면 버튼 이미지가 변경되는 방식을 넣었습니다.
저는 이 버튼을 통해서 드롭다운 필드가 나타나도록 할 건데요.
아이콘이 팔레트? 마냥 있는 필드를 나타내고, 이 아이콘을 드래그 해서 특정한 필드를 생성하는 로직을 구현하고 싶습니다.
이를 위해 차근차근 진행하겠습니다.
const Test = ({ display }) => {
if (display) {
return (
);
} else {
return null;
}
};
왼쪽이 바로 우리의 팔레트 필드가 될 겁니다.
지금은 아주 간단하게 구성이 되어 있습니다.
저는 아이콘을 드래그 하여 필드를 생성할 계획이거든요?
그래서 Basic-Icon-left , right 라는 ClassName 을 가진 div 내부에 각각의 아이콘 이미지를 박아 넣었습니다.
이러한 아이콘 이미지는 Basic-Field-Row 라는 하나의 div 내에 2개씩 줄지어 있을 겁니다.
이거 꾸며주는 CSS도 같이 보시죠.
저는 아래처럼 배치했습니다.
.Basic-Field-Row{
width: 322px;
height: 120px;
display: flex;
justify-content: center;
}
.Basic-Icon-left{
width: 100px;
height: 80px;
margin-right: 20px;
}
.Basic-Icon-left img{
width: 100%;
height: auto;
}
.Basic-Icon-right{
width: 100px;
height: 80px;
}
.Basic-Icon-right img{
width: 100%;
height: auto;
}
이런 식으로, 아이콘을 추가할 때마다 Field-Row 를 추가하는 방식을 사용해서 필드를 구성합니다.
그럼 이제 버튼을 눌렀을 때, 저 display 가 True 인지 False 인지를 할당을 해야겠지요?
const TestFieldSide = () => {
const [currentBasicField, setCurrentBasicField] = useState(BasicFieldChoice);
const [BasicFieldSection, setBasicFieldSection] = useState(false);
const toggleBasicField = () => {
setCurrentBasicField(
currentBasicField === BasicFieldChoice
? BasicFieldChoiceHover
: BasicFieldChoice
);
setBasicFieldSection(!BasicFieldSection);
};
return (
);
};
저는 오른쪽과 같은 방법을 사용했습니다.
먼저 BasicfieldSection 이라는 값에 false 를 할당해 놓습니다.
요거를 아까 위에 만든 팔레트 필드에 있는 display 라는 값에 할당해줌 됩니다.
일전 포스팅에서 사용했던 5번 함수 있죠?
여기에 setBasicFieldSection 을 넣어줍니다.
! 을 앞에 넣어줌으로써 언제나 현재 BasicFieldSection 과는 반대가 되는 값을 할당해주게 됩니다.
이러면 버튼을 누를 때마다, false 또는 True 가 번갈아서
BasicFieldSection 라는 변수에 할당이 되는 겁니다~
요 변수를 <Test> 컴포넌트에 넣어주면 됩니다.
36번 줄처럼 값을 너어주면 이제 버튼을 누를 때마다 아래쪽으로 팔레트 필드가 나타났다가, 다시 누르면 사라지고 뭐 그럴 겁니다.
어때요? 아이콘으로 설정한 이미지가 2개씩 주르륵 나타나고,
버튼을 다시 누르면 없어집니다.
다만, 아직 드래그를 통한 생성은 안 되는군요. 이를 위해 더 진행합시다.
우리는 각 아이콘을 통해 특정한 필드를 생성하려는 거죠?
이를 위해서는 가 아이콘이 각자 고유한 어떤 값을 가지고 있어야 할 겁니다.
이 고유한 값을 통해서 아이콘을 드래그 한 곳에 특정한 필드가 생상되는 거죠.
이를 위해서 Chat GPT 에게 간단한 로직 생성을 부탁했습니다.
const DraggableIcon = ({ value }) => {
const handleDragStart = (e) => {
e.dataTransfer.setData("iconValue", value);
};
return (
{/* 아이콘 내용 */}
);
};
const DropField = () => {
const [fields, setFields] = useState([]);
const handleDrop = (e) => {
e.preventDefault();
const iconValue = e.dataTransfer.getData("iconValue");
const newField = { value: iconValue }; // 필드 객체 생성
setFields([...fields, newField]); // 상태 업데이트
};
const handleDragOver = (e) => {
e.preventDefault();
};
return (
{/* 필드를 여기에 렌더링 */}
{fields.map((field, index) => (
{field.value}
))}
);
};
왼쪽처럼 코드를 제안 받았습니다.
그러니까 DraggableIcon 이라는 컴포넌트를 통해서 기존의 아이콘 구성을 변경하고..
이 아이콘을 드래그 하는 동안에는 Value 내에 필요한 값을 저장하게 됩니다.
그리고 드래그를 해제하는 순간에는, dataTaransfer 이라는 드래그를 하는 중에 생성했던 스토리지에서 iconValue 라는 key 가 가진 Value 를 찾아옵니다.
이 Value 를 통해서, 특정한 필드를 나타내게 되는 겁니다.
그렇다면 이 작업을 보다 구체화 하겠습니다.
// 드래그를 위한 아이콘 컴포넌트
const DraggableIcon = ({ src, type, position }) => {
const [positionName, setPositionName] = useState("Basic-Icon-left");
useEffect(() => {
if (position === "left") {
setPositionName("Basic-Icon-left");
} else {
setPositionName("Basic-Icon-right");
}
}, [position]); // position 값이 변경될 때마다 이 코드가 실행됩니다.
const handleDragStart = (e) => {
e.dataTransfer.setData("FieldType", type);
};
return (
);
};
먼저 저는 왼쪽처럼, DraggableIcon 을 만들었습니다.
이 컴포넌트는 src, type, position 이라는 인자를 건네받아 사용됩니다.
드래그를 하는 동안에는 setData 를 통해서 type 을 저장합니다.
처음에 만들었던 팔레트 내에 있는 아이콘을 아래처럼 바꿔주면 됩니다.
왼쪽에 배열하고 싶다면, left
오른쪽에 배열하고 싶다면, right 를 넣어주도록 설정했습니다.
const FormWindow = () => {
const [fields, setFields] = useState([]);
const handleDrop = (e) => {
e.preventDefault();
const fieldType = e.dataTransfer.getData("FieldType");
const newField = { type: fieldType };
setFields([...fields, newField]);
};
const handleDragOver = (e) => {
e.preventDefault();
};
return (
{fields.map((field, index) => (
))}
);
};
다음은 실제로 이 아이콘을 드래그하고 놓을 공간입니다.
이를 위해서 hanldDrop 이라는 함수를 넣습니다.
이 동작은 드래그를 해제하는 순간 발생하며,
fields 라는 배열에 newField 를 추가하게 됩니다.
결과적으로, fields 라는 배열 안에는 드래그로 아이콘을 넣을 때마다, newField 가 들어가겠죠?
그럼 이것들을 아래의 반복문을 통해서 나타내는 겁니다.
이때, <FieldComponet > 라는 새로운 컴포넌트를 하나 만들었고, 여기에 field.type 이라는 값을 줌으로써 무언가가 나타나도록 하는 겁니다.
FieldComponet 에서는 type 을 그대로 출력하도록 설정했습니다.
const FieldComponent = ({ type }) => {
return (
Type: {type}
{/* 필드 타입에 따른 추가적인 렌더링이나 로직을 여기에 추가할 수 있습니다 */}
);
};
왼쪽이 FieldComponet 입니다.
이걸 코드 내에 같이 지정을 해주면 되겠죠?
지금은 type 뿐이지만, 저는 보다 다양한 인자를 icon 내부에 설정함으로써 더 다양한 필드를 만들 수 있도록 할 계획입니다.
다음처럼 드래그를 통해서 특정한 인자를 FieldComponent 에 전달해서 해당 컴포넌트가 특정한 div 를 생성하게 되었습니다.
이 로직을 활용하여 보다 다양한 인자를 전달하고, 그 다양한 인자를 통해서 보다 복잡한 필드를 생성 가능할 것입니다.
드래그 앤 드랍 기능을 사용하여 필드를 생성하는 로직을 이해했습니다.
이해한 로직을 바탕으로 다음 번에는 더 복잡한 기능이 생성 완료된 페이지로 진화가 가능할 것 같습니다.^^