JSON 데이터 수정하기 w/ format: table

format: table을 통해 JSON 형태의 데이터를 수정하는 UI 화면을 구성하는 방법을 안내드립니다.

핵심

  • format: table: 데이터를 테이블 UI로 표시 및 입력.
  • headers: 테이블 열의 입력값 형식, 유효성, 표시방식을 설정.
  • requestFn: 입력 데이터를 서버에 보낼 JSON 형식으로 가공하고, 금액 범위 중복 검사를 수행.

예제 이미지와 YAML

menus:
- path: pages/sOCGir
  name: format table
pages:
- path: pages/sOCGir
  title: d=65 wine_stock의 property_json.shippingRules[] 를 수정합니다.
  blocks:
    - type: query
      resource: mysql.qa
      sqlType: update
      sql: |
        UPDATE wine_stock 
        SET property_data = :shippingRules
        where id = 65
      params:
        - key: shippingRules
          label: 배송비 규정
          format: table
          style:
            width: 700px
          showHeaders: false
          class: table text-xs
          headers:
            minAmount:
              label: 배송비시작
              format: number
              required: true
              postfix: 원 이상
              postfixStyle:
                width: 50px
            maxAmount:
              prefix: "~"
              format: number
              postfix: 원 미만
              postfixStyle:
                width: 50px
              placeholder: 비어있으면 최대금액
            shippingCost:
              format: number
              postfix: 원          
          value: # 기본값이 필요한 경우에 입력 (예제 데이터)
            - minAmount: 
                value: 0
              maxAmount: 
                value: 50000
              shippingCost: 
                value: 3000
            - minAmount: 
                value: 5000
              maxAmount: 
                value: ""
                placeholder: (최대)
              shippingCost: 
                value: 0
      reloadAfterSubmit: true
      
      requestFn: |
        const shippingRules = params.find(e => e.key == 'shippingRules')

        shippingRules.value = JSON.stringify({ 
          shippingRules: shippingRules.value.map(row => {
            return {
              minAmount: row.minAmount.value,
              maxAmount: row.maxAmount.value,
              shippingCost: row.shippingCost.value,
            }
          })
        })
      
    - type: query
      resource: mysql.qa
      title: id=65 wine_stock의 property_json의 일부분을 수정
      sqlType: select
      sql: |
        select id, property_data from wine_stock 
        where id = 65
      display: form
      responseFn: |
        rows = rows.map(e => {
          e.shippingRules = (e.property_data || {}).shippingRules || []
          e.shippingRules = e.shippingRules.map(row => {
            for (const key in row) {
              row[key] = { value: row[key] }
            }
            return row
          })
          return e
        })

        return rows
      columns:
        property_data:
          hidden: true
        shippingRules:
          label: 배송비 규정
          updateOptions:
            type: query
            resource: mysql.qa
            sqlType: update
            sql: |
              UPDATE wine_stock 
              SET property_data = :value
              where id = :id

            requestFn: |
              const value = params.find(e => e.key == 'value')
              const shippingRules = params.find(e => e.key == 'shippingRules')
              // console.log('>>>>>>', {value, params})

              function validateShippingRules(rules) {
                const errors = [];

                for (let i = 0; i < rules.length; i++) {
                  const currentRule = rules[i];
                  for (let j = i + 1; j < rules.length; j++) {
                    const nextRule = rules[j];

                    // 겹치는 조건: 두 범위가 서로 교차하는 경우
                    const isOverlapping =
                      (currentRule.maxAmount.value === null || nextRule.minAmount.value < currentRule.maxAmount.value) &&
                      (nextRule.maxAmount.value === null || currentRule.minAmount.value < nextRule.maxAmount.value);

                    if (isOverlapping) {
                      errors.push(`Overlap detected between rule ${i + 1} and rule ${j + 1}`);
                    }
                  }
                }

                return errors.length > 0 ? errors : "No overlaps detected.";
              }
              const errors = validateShippingRules(shippingRules.value)
              if (errors != "No overlaps detected.") {
                throw new Error(['금액범위를 확인해주세요.', ...errors].join('<br />'))
              }

              value.value = JSON.stringify({ 
                shippingRules: shippingRules.value.map(row => {
                  return {
                    minAmount: row.minAmount.value,
                    maxAmount: row.maxAmount.value,
                    shippingCost: row.shippingCost.value,
                  }
                })
              })

          format: table
          style:
            width: 700px
          class: table text-xs
          headers:
            minAmount:
              label: 배송비시작
              format: number
              postfix: 원 이상
              postfixStyle:
                width: 50px
            maxAmount:
              label: 금액 (없으면 최대)
              prefix: "~"
              format: number
              postfix: 원 미만
              postfixStyle:
                width: 50px
              placeholder: 비어있으면 최대금액
            shippingCost:
              label: 배송비부과
              format: number
              postfix: 원                 

format: table

  • 테이블 형식으로 데이터를 표시하거나 입력받기 위한 설정입니다.
  • 사용자가 행(row) 기반으로 데이터를 직관적으로 관리할 수 있도록 UI를 생성합니다.
  • 관련 스타일:
    • width: 700px: 테이블 너비 설정.
    • showHeaders: 테이블 헤더 표시여부
    • class: table text-xs: 테이블의 클래스 지정(작은 글자 크기).

headers

  • 테이블 열(컬럼)별 속성을 정의합니다.
  • 각 열의 데이터 형식, 입력 유효성, 표시 형식을 세부적으로 지정합니다.
  • label, format: 헤더 컬럼 라벨, 포맷
  • prefix, postfix: 입력 필드 전후 텍스트
  • postfixStyle: postfix 스타일

requestFn

  • 사용자가 입력한 테이블 데이터를 데이터베이스 업데이트에 적합한 형식으로 변환하는 로직입니다.
  • 주로 입력 데이터를 JSON 형태로 가공하거나 유효성 검사를 수행합니다.

주요 역할:

  • 데이터 가공:

    • 사용자 입력값을 params에서 가져옴.
    • shippingRules.value를 JSON 형태로 직렬화하여 데이터베이스에 저장 가능하도록 준비.
    • 각 행(row)을 { minAmount, maxAmount, shippingCost }로 변환.
  • 유효성 검사:

    • 금액 범위가 겹치는지 확인 (validateShippingRules 함수).
    • 겹치는 범위가 발견되면 에러 메시지 발생:
      "금액범위를 확인해주세요.<br />Overlap detected between rule 1 and rule 2".

처리 예제 일부:

자세한 내용은 상단 YAML 전체 예제를 참고해주세요.

const shippingRules = params.find(e => e.key == 'shippingRules');

// JSON 직렬화
shippingRules.value = JSON.stringify({
  shippingRules: shippingRules.value.map(row => {
    return {
      minAmount: row.minAmount.value,
      maxAmount: row.maxAmount.value,
      shippingCost: row.shippingCost.value,
    };
  }),
});

// 금액 범위 유효성 검사
function validateShippingRules(rules) { ... }

관련하여 도움이 필요하시면 댓글 등으로 문의주시면 안내드리겠습니다.
감사합니다.