Notice
Recent Posts
Recent Comments
Link
«   2025/10   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

Mendix개발일지

[Mendix] React Widget with Library 본문

Mendix

[Mendix] React Widget with Library

라이루이 2024. 5. 14. 14:45

저번에는 Widget Exam을 해보았다면 이번에는 정말 만들어보고 싶은 것을 만들어 볼 것이다.

Library를 사용하고 Datasource 에 있는 데이터를 Grid.js 를 사용해서 보여주는 것을 만들어볼 예정이다.

먼저 다운로드를 받아주자!!

npm install --save gridjs && npm install --save gridjs-react

 

Grid.js 의 사용법을 알아야지 진행을 할 수 있어서 사용법부터 한번 살펴보겠다.

정말 간단하게 표 형태의 Grid를 구현할 수 있다.

<Grid
  data={[
    ['John', 'john@example.com'],
    ['Mike', 'mike@gmail.com']
  ]}
  columns={['Name', 'Email']}
  search
  pagination={{
    limit: 1,
  }}
/>

 

그렇다면 내가 하고싶은 Datasource 에서 데이터를 가져와서 뿌려주기 위해서는 어떻게 해야될까??

일단은 Mendix React 프로젝트를 하나 생성하고 [Module].xml에 아래를 추가한다.

아래의 내용은 Datasource 를 Properties 에 생성하는 하기 위해서 하는 작업이다

💡XML TYPE DOC
 링크를 가보면 Properties에 원하는 옵션을 줄 수있다. 검색할때 Ctrl+f 를사용해서 type=”[원하는타입]”을하면 한번에 찾을 수 있다.
<?xml version="1.0" encoding="utf-8"?>
<widget id="mendix.gridjstest.GridjsTest" pluginWidget="true" needsEntityContext="true" offlineCapable="true"
        supportedPlatform="Web"
        xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../node_modules/mendix/custom_widget.xsd">
    <name>Gridjs Test</name>
    <description>My widget description</description>
    <icon/>
    <properties>
        <propertyGroup caption="General">
            <property key="gridData" type="datasource" isList="true" required="true">
                <caption>Data source</caption>
                <description />
            </property>
        </propertyGroup>
    </properties>
</widget>

 

XML에 맞게 생성된 옵션!! widget은 직접 위치에 넣어주어야 한다.

 

 

좋다 XML에 Datasource 를 추가했고 알아서 받아올테니 소스코드를 작성하면된다.

일단은 소스코드를 먼저 한번 훑어보고 가겠다.

// GridjsTest.tsx
import { ReactElement, createElement } from "react";
import { GridjsTestComponent } from "./components/GridjsTestComponent";

import { GridjsTestContainerProps } from "../typings/GridjsTestProps";

export function GridjsTest({ gridData }: GridjsTestContainerProps): ReactElement {
    return <GridjsTestComponent name={""} class={""} gridData={gridData} />;
}

// GridjsTestComponent.tsx
import { ReactElement, createElement, useEffect, useState } from "react";
import { GridjsTestContainerProps } from "../../typings/GridjsTestProps";
import { Grid } from "gridjs-react";
import "gridjs/dist/theme/mermaid.css";

interface ItemWithSymbol {
    [key: symbol]: any; // Symbol(mxObject)
}

function handleuserData(item: ItemWithSymbol): any {
    const symbols = Object.getOwnPropertySymbols(item);
    const mxObject = item[symbols[0]];
    // console.log(mxObject.jsonData.attributes.age.value, mxObject.jsonData.attributes.name.value);
    const age: string = mxObject.jsonData.attributes.age.value;
    const name: string = mxObject.jsonData.attributes.name.value;
    return { name, age };
}

export function GridjsTestComponent({ gridData }: GridjsTestContainerProps): ReactElement {
    const [userData, setUserData] = useState<string[][]>([]);
    //  useEffect는 컴포넌트가 렌더링될 때마다 실행
    useEffect(() => {
        if (gridData.items) {
            const tempItems = gridData.items.map((item: any) => {
                const itemWithSymbols: ItemWithSymbol = item;
                const userData = handleuserData(itemWithSymbols);
                return [userData.name, userData.age]; // Create sub-array for each row
            });
            setUserData(tempItems);
        }
        // 의존성을 가지고있어서 값이 업데이트 된다면 UseEffect함수실행
    }, [gridData.items]);

    return (
        <div>
            <h1>My Data Grid</h1>
            <Grid
                data={userData} // Use mapped data
                columns={["Name", "Age"]} // Set column titles
                search // Enable search feature
                pagination={{
                    limit: 5 // Number of items per page
                }}
            />
        </div>
    );
}

 

💡Point

Grid.js와 연동하는 것은 전혀 문제가 없었는데 가장 힘들었던 점은 Mendix와 React의 interface였다.

문서를 찾아봐도 Type만 알려주고 나머지는 알아서 하라는 식으로 알려주기 때문에 막막했지만…

하나부터 차근차근 살펴보겠다는 마음가짐으로 개발자모드를 사용해서 뜯어보았다.

11번째줄을보면 데이터를보면 Symbol(mxObject) 형식으로 들어가있다. Symbol형식은 사용해본적이 없어서 찾아봤다.

 

 

💡 심볼(symbol)은 ES6에서 새롭게 추가된 7번째 타입으로 변경 불가능한 원시 타입의 값이다.
💡 심볼은 주로 이름의 충돌 위험이 없는 유일한 객체의 프로퍼티 키(property key)를 만들기 위해 사용한다.

mxObject라는 원시타입을 만들기 위해서 만든 것이구나… 하여튼 중요한거는 Symbol형식의 데이터를 사용하기위해서 Object.getOwnPropertySymbols 를 사용해서Object형식으로 바꿔주었다.

console 창을 본다면 jsonData 이보인다… 내가 사용하고싶었던 값이 저기 숨어있던 것이다. 그래서 저 값을 사용해서 데이터를 만들어 주었다.

function handleuserData(item: ItemWithSymbol): any {
    const symbols = Object.getOwnPropertySymbols(item);
    const mxObject = item[symbols[0]];
    // 이 곳에서 mxObject를 참조한다.
    const age: string = mxObject.jsonData.attributes.age.value;
    const name: string = mxObject.jsonData.attributes.name.value;
    return { name, age };
}
const [userData, setUserData] = useState<string[][]>([]);
useEffect(() => {
    if (gridData.items) {
        // 이 부분에서 데이터를 만들어준다!!!
        const tempItems = gridData.items.map((item: any) => {
            const itemWithSymbols: ItemWithSymbol = item;
            const userData = handleuserData(itemWithSymbols);
            return [userData.name, userData.age]; 
        });
        setUserData(tempItems);
    }
}, [gridData.items]);

 

소스코드까지 작성이 완료 되었다면… npm run build 를 실행시켜서 mendix에서 불러와 보도록하면!!!

아래처럼 Grid.js 에 정상적으로 표시된다.

 

 

'Mendix' 카테고리의 다른 글

[Mendix] TreeNode  (0) 2024.05.14
[Mendix] selectBox Widget 구현  (0) 2024.05.14
[Mendix] Custom Widget  (0) 2024.05.14
[Mendix] multi file upload  (0) 2024.05.14
[Mendix] 커스텀로그인  (1) 2024.05.14