이 블로그에서는 위젯에서 애플리케이션의 영구적인 데이터 변경을 하는 방법, 위젯을 결합하여 매끄러운 최종 사용자 경험, 사용자 정의 후크 등을 만드는 방법에 대해 알아봅니다.
이는 여러 부분으로 구성된 시리즈의 세 번째 블로그입니다. 블로그 1과 2는 여기에서 찾을 수 있습니다. 위젯을 빌드하세요 Mendix React로 - 1부 - 색상 카운터 및 위젯을 빌드하세요 Mendix React Part 2 — 타이머.
시작하기에 앞서, 작은 주의사항을 알려드리겠습니다. 이 빌드에서는 VS Code의 일부 기능을 활용했으며, 다른 IDE를 선호하는 경우 지침이 다를 수 있습니다.
우리가 무엇을 만들고 있는가
Mendix 최근에 출시되었습니다 에픽 스, 모든 기능을 갖춘 새로운 스토리 관리 도구!
이것의 일부로, 스토리를 드래그 앤 드롭할 수 있는 정말 멋진 구성 요소가 있습니다. 비슷한 것을 만들어 보는 것이 멋질 것이라고 생각했습니다.

모든 칸반 보드는 다음과 같은 몇 가지 작업을 수행할 수 있어야 합니다.
- 사용자가 칸반 단계를 설정하도록 허용
- 드래그하여 항목의 단계를 변경할 수 있습니다.
- 섹션의 항목 정렬 순서를 드래그하여 변경할 수 있습니다.
시작 가이드
시작하려면 위젯 생성기를 실행하여 위젯을 빠르게 스캐폴딩하여 위젯을 스캐폴딩합니다. 다음 명령을 실행합니다.
yo @mendix/widget kanban
위젯 속성을 구성할 때 기본 옵션을 선택하고 다음을 확인하십시오. 타입스크립트를 사용하세요.
다음으로 위젯과 위젯 간의 인터페이스를 업데이트할 것입니다. Mendix Kanban.xml을 업데이트하여 이를 수행합니다. 이를 위해 위젯 사용자가 무엇을 지정할 수 있도록 Datasource 항목 목록을 추가합니다. Mendix 사용하고 싶은 엔터티.
위젯 내에서 항목을 실제로 렌더링하기 위한 두 가지 옵션이 있습니다. 기존 JSX를 사용하거나 사용자가 원하는 디자인을 빌드하도록 허용할 수 있습니다. Mendix. 두 번째 옵션에는 세 가지 주요 장점이 있습니다.
- 자식 데이터가 표시되어야 하는 구조를 규정하는 것을 방지합니다.
- 편집하기 어려운 컴파일된 위젯 파일에 있는 코드를 숨기지 않습니다.
- 사용자가 WYSIWG 편집기를 활용할 수 있도록 합니다. Mendix
목록 렌더링
옵션 2가 승리합니다! 이를 구현하려면 '를 사용할 수 있습니다.위젯' 태그에서 플러그형 위젯 API. 업데이트된 Kanban.xml에는 이제 다음이 포함됩니다.
아이템 항목 목록 콘텐츠 데이터 소스를 사용하는 위젯
다음으로, 다음을 포함하도록 Kanban.TSX 파일을 업데이트할 수 있습니다.
Kanban({ widgetList, items }: KanbanContainerProps) 함수를 내보냅니다. ReactElement { return ( {항목.항목 && 항목.항목.맵(항목 => { 위젯리스트.get(항목)을 반환합니다.})} ); }
위 코드에서는 몇 가지 일이 발생하므로 이를 나누어 설명하겠습니다.
- “위젯리스트”우리의 위젯 인터페이스는 다음과 같습니다. Mendix 모델에서 "widgetList"를 마우스 오른쪽 버튼으로 클릭하고 '유형 정의로 이동'을 클릭하면 이 유형에 대한 문서를 볼 수 있습니다.
내보내기 선언 인터페이스 ListWidgetValue {
* 제공된 객체 item을 기반으로 렌더링된 React 노드 형태로 사용자가 구성한 위젯을 반환합니다.*
* @param item 연결된 데이터 소스의 {@link ObjectItem} 인스턴스.*/
get: (항목: ObjectItem) => ReactNode;
}
기본적으로 이것은 위젯에 대한 하나의 get 함수가 있으며 ReactNode를 렌더링하기 위해 ObjectItem이라는 것을 기대한다는 것을 알려줍니다.
- "항목"은 ListValue(a)로 액세스할 수 있는 데이터 소스입니다. Mendix-정의된 유형), "항목"을 마우스 오른쪽 버튼으로 클릭하고 '유형 정의로 이동'을 클릭하면 이 유형에 대한 설명서를 볼 수 있습니다. 이 설명서에서 ObjectItem 배열에 액세스할 수 있음을 알 수 있습니다. .아이템 재산
그런 다음 내장 함수인 JS map을 사용하여 항목 목록의 각 요소를 반복하고 항목의 'get' 함수를 사용하여 결과를 반환할 수 있습니다.
- 우리는 그 우리의 함수를 감싸다 in 중괄호 JavaScript임을 보여주고 이를 래핑합니다. 부모 div 각 항목을 렌더링하려면
- 마지막으로 다음을 추가합니다. 3항식 목록에 항목이 없는 경우 함수를 호출하지 않도록 합니다.
지원
구현을 테스트하기 위해 위젯의 'tests' 폴더에 테스트 프로젝트를 설정했습니다. 이는 다음에서 한 것과 같습니다. 블로그 1.
우리는 라는 엔티티를 추가합니다 항목 문자열 속성을 사용하여 내용

그런 다음 우리는 몇 가지 마이크로 흐름을 추가합니다. After Start Up Microflow에서 몇 가지 $Items를 생성합니다.

그런 다음 터미널에서 위젯을 빌드할 수 있습니다. npm run build .
우리가 우리에게 돌아올 때 Mendix 모델을 클릭하고 F4를 누르면 위젯을 홈페이지에 배치할 수 있습니다.

여기에 '라는 클래스가 있는 간단한 컨테이너를 추가했습니다.카드' 그리고 내용을 표시하는 문자열. 그리고 보일라! 렌더링됩니다.

드래그 앤 드롭
정적 목록을 갖는 것은 좋은 시작이지만, 그 항목을 이리저리 옮길 수 있어야 합니다!
React 드래그 앤 드롭 라이브러리를 선택해 봅시다. 우리 스스로 이걸 만들 수도 있습니다.그리고 좀 똑똑해 Mendix 개발자들은 이미 그렇게 했습니다!) 하지만 거기에는 잘 지원되고 많이 사용되는 매우 광범위한 라이브러리 선택.
나는 같이 갔다 리액트-뷰티풀-dnd 그것이 가지고 있기 때문에 사용하기 쉬운 API이며 매우 풍부한 기능의.
그런 다음 위젯 디렉토리(./kanban)로 이동하여 다음 명령을 실행하여 드래그 앤 드롭 라이브러리를 가져옵니다.
npm i react-beautiful-dnd .
설명서를 읽어보니 위젯에 필요한 세 가지 주요 영역이 있습니다.

<DragDropContext />- 드래그 앤 드롭을 활성화하려는 애플리케이션 부분을 래핑합니다.<Droppable />- 떨어뜨릴 수 있는 영역.<Draggable />- 무엇을 끌고 다닐 수 있습니까?
1단계 - 드래그 가능
그러면 가장 낮은 수준부터 시작해서 아이템을 드래그 가능하게 변환해 보겠습니다.
먼저 ItemList를 별도의 함수로 분리하지만, 지금은 개발의 편의를 위해 컴포넌트 내에 유지하겠습니다(나중에 별도의 컴포넌트로 옮길 수 있습니다).
Kanban({ widgetList, items }: KanbanContainerProps) 함수를 내보냅니다. ReactElement {
const 아이템리스트 = (): ReactElement => {
반품 ( {항목.항목 && 항목.항목.맵(항목 => { 위젯리스트.get(항목)을 반환합니다.})} );
}
반품 ( ) }
각 목록 항목을 드래그 가능하게 하려면 위젯을 Draggable 구성 요소로 래핑해야 합니다. 고유한 ID를 기대합니다 드래그 가능한 항목의 경우 — 항목을 주문하기 위한 인덱스, 그리고 구성 요소를 렌더링하는 자식 함수.
나머지 구현에 대한 react-beautiful-dnd 라이브러리의 설명서를 따르면 다음과 같은 코드가 생성됩니다.
const ItemList = (): ReactElement => { 반환 ( {항목.항목 &&항목.항목.맵((항목, i) => { 반환합니다( {제공됨 => ( {위젯목록.get(항목)} )} ); })} ); };
여기서 우리가 한 일은 위젯 구성 요소를 '드래그 가능한' 래퍼로 감싸서 참조와 속성을 전달할 수 있게 한 것입니다.
참조는 이 블로그에서 아직 다루지 않은 개념이며 React의 핵심 부분입니다. 이는 본질적으로 페이지 내의 요소에 액세스하는 방법이며 이 경우에는 드래그되는 내용을 추적하기 위한 것입니다. Refs와 DOM – React.
2단계 - 드롭 가능
이제 드래그 가능한 구성 요소가 있으므로 드래그 앤 드롭 캔버스를 만들어야 합니다.
이를 위해 위에서 설명한 것과 매우 유사한 패턴을 사용하여 Draggable 구성 요소의 ItemList를 Droppable 컨테이너로 래핑해야 합니다.
{제공됨 => ( )}
3단계 - 맥락
마지막으로 해당 기능이 존재하는 드래그 앤 드롭 컨텍스트를 제공해야 합니다.
{제공됨 => ( )}
컨텍스트는 항목이 드래그되면 함수가 호출되기를 기대합니다. 지금은 함수가 호출되었다는 것을 기록해 보겠습니다.
현재 우리의 코드는 다음과 같습니다.
Kanban({ widgetList, items }: KanbanContainerProps) 함수를 내보냅니다. ReactElement { const ItemList = (): ReactElement => { return ( {항목.항목 && 항목.항목.맵((항목, i) => { 반환( {제공됨 => ( {위젯목록.get(항목)} )} ); })} ); };
함수 onDragEnd(결과: DropResult): void { console.log("드래그됨"); }
반품 ( {제공됨 => ( )} ); }
우리가 실행하면 npm run build 그리고 우리의 것을 다시 실행 Mendix 앱에서, 이제 우리는 카드를 끌고 다닐 수 있어요! 일종의…

이 문제는 나중에 다시 살펴보겠습니다. 가장 중요한 부분은 아이템을 이리저리 끌어다 놓을 수 있다는 것입니다.
여러 열
따라서 하나의 목록에서 항목을 위아래로 끌 수는 있지만, 실제로는 상태를 확인하기 위해 열 사이에서 항목을 끌 수 있게 하고 싶습니다.
우리는 위젯 사용자가 원하는 열의 수를 지정할 수 있기를 바랍니다.
이를 위해 다음을 사용할 수 있습니다. '사물' Kanban.xml에서. 기존 속성을 다음과 같이 객체 목록에 래핑하기만 하면 됩니다.
섹션 이름 이름 섹션 항목 항목 목록 콘텐츠 데이터 소스를 사용하는 위젯
눈이 빠른 분들은 제가 칼럼을 추적할 수 있도록 이름을 추가했다는 사실도 알아차리실 겁니다.
열면 Mendix 우리는 우리의 사랑스러운 새로운 인터페이스를 확인할 수 있습니다:

멋지네요. 하지만 이제 열을 렌더링해야 하니 위젯으로 돌아가 봅시다...
사실 이는 매우 간단합니다.
먼저, 각 객체에 대한 열을 렌더링하도록 JSX를 업데이트해 보겠습니다.
{myObject.map((obj, i) => { 반환합니다( {제공됨 => ( )} ); })}
우리도 만들어야 해요 드롭 가능한 ID 고유성을 확인하고 ItemList에 일부 속성을 전달합니다.
{myObject.map((obj, i) => { 반환합니다( {제공됨 => ( )} ); })}
이는 또한 새로운 소품을 수용하기 위해 아이템 목록을 업데이트해야 한다는 것을 의미하며, 여기서 우리는 그것을 읽기 쉬운 것으로 리팩토링하는 것이 좋습니다. 저는 컴포넌트 폴더에 두 개의 새 파일을 만들었습니다.
드래그 가능.TSX
"react"에서 {ReactElement, createElement}를 가져옵니다. "react-beautiful-dnd"에서 {Draggable}을 가져옵니다. "mendix"에서 {ObjectItem, ListWidgetValue}를 가져옵니다.
내보내기 인터페이스 DraggableProps {항목: ObjectItem; i: 숫자; 위젯 목록: ListWidgetValue;}
DraggableItem({ item, i, widgetList }: DraggableProps) 함수를 내보냅니다. ReactElement { return ( {제공됨 => ( {위젯목록.get(항목)} )} ); }
그리고 ItemList.TSX
"react"에서 {ReactElement, createElement}를 가져옵니다. "mendix"에서 {ListValue, ListWidgetValue}를 가져옵니다. "./Draggable"에서 {DraggableItem}을 가져옵니다.
내보내기 인터페이스 ItemListProps {항목: ListValue; 위젯목록: ListWidgetValue;}
export const ItemList = ({항목, 위젯리스트}: ItemListProps): ReactElement => { return (항목 && ( {항목.항목 && 항목.항목.맵((항목, i) => { 반환 ; })} ) ); };
스타일링
칸반 보드에 약간의 스타일을 추가해서 못생긴 오리 새끼를 아름다운 백조로 바꿔야 합니다.
우리는 이를 두 가지 주요 방법으로 수행할 것입니다.
- CSS 클래스를 활용하여 'className' prop 모든 dom 요소에는
- 코드에서 계산된 속성(예: 열 너비)을 활용하기 위해 인라인 스타일 활용
먼저 Kanban.css 파일을 업데이트해 보겠습니다.
.kanban-col { 여백: 15px; 패딩: 10px; 배경: #9bedff; 테두리 반경: 15px; }
.kanban-col h6 { 텍스트 정렬: 가운데; }
그런 다음 몇 가지 추가적인 DOM 요소, 클래스, 스타일을 사용하여 다음과 같은 결과를 얻을 수 있습니다.
"./components/ItemList"에서 {ItemList}를 가져옵니다. "../typings/KanbanProps"에서 {KanbanContainerProps}를 가져옵니다.
"./ui/Kanban.css"를 가져옵니다.
Kanban({myObject}: KanbanContainerProps) 함수를 내보냅니다. ReactElement
함수 onDragEnd(결과: DropResult): void { console.log("드래그됨"); }
반품 ( {myObject.map((obj, i) => { 반환합니다( {제공됨 => ( {obj.섹션이름} {제공됨.자리 표시자} )} ); })} ); }
잠깐요...저게 뭐예요? ${100/myObject.length}%
이것은 템플릿 리터럴 이를 통해 JS에서 문자열을 "로 작성하고 표현식을 ${}로 래핑하여 빠르게 문자열을 작성할 수 있습니다.
하지만 위젯으로 돌아와서...이제 항목이 있는 사용자 정의 열이 있습니다.

드래그 앤 드롭 액션
이제 우리는 드래그 앤 드롭이 실제로 무언가를 하길 원합니다...

이를 위해 데이터 소스와 함께 Pluggable Widget 액션 API를 활용하겠습니다.
따라서 먼저 Kanban.xml에 있는 객체에 두 개의 새 속성을 추가해 보겠습니다.
섹션 항목 항목 목록 모든 항목 항목 목록
데이터 소스에 작업을 연결하면 매개변수를 사용하여 작업을 실행할 수 있습니다. Mendix. 이렇게 하면 항목의 속성을 변경할 수 있습니다.
이제 우리는 "를 업데이트할 수 있습니다.onDragEnd”동작을 실행하는 함수입니다.
react-beautiful-dnd에 대한 설명서를 읽어보면 onDragEnd가 result 객체를 수신하여 draggableId와 droppableID에 액세스할 수 있음을 알 수 있습니다. 이를 사용하여 어떤 Item이 드래그되고 어디로 드래그되는지(따라서 어떤 작업을 호출해야 하는지) 알아낼 수 있습니다.
첫 번째로 해야 할 일은 결과를 구조 분해하고 올바른 객체를 찾는 것입니다.
const { 소스, 대상 } = 결과; const destObj = myObject[parseInt(대상.삭제 가능한 ID, 10)];
여기서 우리는 droppableId(객체의 인덱스로 설정)를 구문 분석하고 이를 사용하여 객체를 검색합니다. 나의 객체 정렬.
올바른 객체를 얻으면 목록에서 해당 객체를 찾아 드래그되는 항목의 표현을 얻을 수 있습니다. 모든 항목.
const destObjItem = destObj.allItems.items!.find(item => { return item.id === result.draggableId; });
동일한 객체에 속한 항목에 대해서만 작업을 호출할 수 있으므로 모든 객체에 대해 allItems를 지정해야 합니다.
그런 다음 객체에서 작업을 실행할 수 있습니다.
const actionOnObj = destObj.action!.get(destObjItem!); actionOnObj.실행가능하다면 { actionOnObj.실행(); }
항목이 목록으로 끌려갔는지 확인하기 위해 몇 가지 검사를 추가하고 최종 함수는 다음과 같아야 합니다.
함수 onDragEnd(결과: DropResult): void { const { 소스, 대상 } = 결과; if (!대상) { 반환; } const destObj = myObject[parseInt(대상.droppableId, 10)]; const destObjItem = destObj.allItems.items!.find(항목 => { 반환 항목.id === 결과.draggableId; }); const actionOnObj = destObj.action!.get(destObjItem!); if (actionOnObj.canExecute) { actionOnObj.execute(); } }
이렇게 하면 드래그 앤 드롭 칸반 보드를 작동시킬 준비가 잘 되었습니다. Studio Pro에서 몇 가지 작업을 해야 합니다. 먼저 다양한 상태를 나타내는 Status 속성을 추가해 보겠습니다.

이제 설정하려는 각 상태에 대한 나노플로우를 추가해 보겠습니다.

이제 관련 상태가 있는 모든 항목과 올바른 놓기 동작을 설정하여 각 섹션을 구성하고, AllItems에 데이터베이스의 모든 항목에 대한 링크를 추가해 보겠습니다.

드래그 앤 드롭도 있죠!

정렬
거의 다 됐습니다. 정렬을 도입하는 것이 한 가지 더 남았습니다. 이를 위해 Pluggable Widgets에서 데이터를 가져오는 데 유용한 패턴을 사용하려고 합니다.
이상적으로는 '항목'의 값을 사용하여 이를 완전히 관리해야 하지만 현재 Pluggable Widget API에는 제한이 있습니다. 즉, 목록에 포함된 객체의 속성을 직접 변경할 수 없습니다. 이 제한은 제거될 로드맵에 있습니다. 그동안 다음과 같은 접근 방식을 취할 수 있습니다.
정렬 순서를 저장하는 것으로 시작해 보겠습니다. Mendix 엔티티: 항목.

이 작업을 진행하는 동안 ASU를 업데이트하여 정렬 값이 있는 항목으로 매번 데이터베이스를 다시 채웁니다.

위젯으로 돌아가서 Kanban.xml을 업데이트하여 새로운 '정렬' 속성 그룹을 만들어 보겠습니다. 이를 통해 항목을 드래그할 때 이전 및 업데이트된 정렬 인덱스를 저장하는 데 사용할 수 있습니다.
새로운 정렬 정렬 값 저장소 이전 정렬 정렬 값 저장소
그런 다음 onDrag 함수를 업데이트하여 이러한 속성을 전달할 수 있습니다. Mendix 모델:
함수 onDragEnd(결과: DropResult): void { const { 소스, 대상 } = 결과; if (!대상) { 반환; } const destObj = myObject[parseInt(대상.droppableId, 10)]; const destObjItem = destObj.allItems.items!.find(항목 => { 반환 항목.id === 결과.draggableId; });
prevSort.setValue(새로운 Big(소스.인덱스)) newSort.setValue(새로운 Big(대상.인덱스))
const actionOnObj = destObj.action!.get(destObjItem!); actionOnObj.실행가능이면 { actionOnObj.실행(); } }
우리가 우리에게 돌아가면 Mendix 모델을 사용하면 이러한 값을 사용하여 정렬 논리를 구축할 수 있습니다.
이전 및 새로운 정렬 값을 보관할 Entity를 설정해 보겠습니다.

이제 이 엔터티를 제공하는 데이터 뷰로 위젯을 래핑해 보겠습니다.

그런 다음 위젯을 구성하여 정렬 값을 엔터티에 전달할 수 있습니다.

위젯을 데이터 뷰에 래핑했으므로 이제 KanbanHelper를 onDrag에서 실행되는 작업에 매개변수로 추가할 수 있습니다.

우리는 각각의 onDrag 나노플로에서 3가지 주요 작업을 수행합니다.
- 스토어 전에, 시작 상태 항목의 (이것은 정렬 계산을 위해 항목이 열이 변경되었는지 여부를 결정합니다)
- 아이템 업데이트 새로운 상태 및 새로운정렬 가치
- 구현 정렬 논리 나머지 항목으로
정렬 논리의 경우 Sub nanoflow로 구축할 수 있습니다.

이것이 여기서 어떻게 구성되었는지에 대한 세부 사항은 설명하지 않겠지만, 나노플로우는 리소스 섹션에서 찾을 수 있습니다. Github 레포.
그런 다음 애플리케이션을 실행하고 마지막으로 한 번 테스트해 보면…

제품 개요
이제 우리는 모든 것을 노래하고, 모든 것을 춤추는 칸반 보드를 가지고 있습니다! 우리는 react-beautiful-dnd 라이브러리를 사용했고, Mendix 위젯과 몇 가지 간단한 나노플로를 사용하여 완전히 기능적이고 사용자 정의가 가능한 칸반 보드를 구축합니다.
이 위젯의 최종 상태는 여기에서 확인할 수 있습니다. GitHub – joe-robertson-mx/kanban-widget
여러분이 이 칸반 보드를 구현하고 만든 것을 자랑하고 싶다면, 아래에 댓글로 공유하세요.
다음 번에 우리는 구현을 살펴볼 것입니다 지도 Pluggable Widgets에서 복잡한 외부 라이브러리를 사용하는 방법과 빌드에 사용자 정의 파일을 포함하는 방법을 알아봅니다.