본문 바로가기
웹 개발/Front End

vue3-excel-editor 사용법

by L3m0n S0ju 2024. 6. 1.

 

 

서브회원 초대하기 모달에서 excel기능을 사용할 일이 생겨서 vue3-excel-editor를 사용해봤습니다.

Vue3 를 처음 사용해봐서 vue3-excel-editor 사용에 있어서 놓친 부분이 많지만 나중에 여유가 생기면 다시 도전하려고 합니다.

 

 

 

필요기능

1. 이메일 중복 시 -> 유효성 통과 X

2. 모든 입력칸 미입력시 -> 유효성 통과 X

3. 유효하지 않은 이메일, 이름, 휴대폰 번호 형식 -> 유효성 통과 X

4. 입력한 총 건수 표시

 

 

 

 

 

 

디자인 적용 후(아직 디자인 깨지는 부분 있음)

 

 

 

서브호원을 초대하는 모달에서 vue3-excel-editor를 사용했고 아래 코드 예시는 vue3-excel-editor과 관련된 메서드들을 가져왔습니다. 필요한 경우 커스터마이징 할 수 있습니다. 

 

SubUserInviteModal.vue

<template>
  <BaseModal :visible="isInviteVisible">
    <BaseModalHeader :close-button="true">서브회원 초대하기</BaseModalHeader>
    <BaseModalBody>
      <ul class="txt-clause-desc">
        <li>'''생략'''</li>
      </ul>
      <div class="invite-area">
        <div class="sub-scroll">
          <vue-excel-editor
            ref="grid"
            v-model="users"
            :page="3"
            no-footer
            @update="handleUpdate"
            free-select
          >
            <vue-excel-column
              field="idx"
              label="No."
              type="noIdx"
              width="60px"
              text-align="center"
              key-field
              readonly
            />
            <vue-excel-column
              :validate="CopbizValidate.validateEmail"
              field="email"
              :label="Copbiz.columnTextHTML('이메일 주소', '[필수]')"
              type="string"
              width="250px"
              text-align="center"
            />
            <vue-excel-column
              :validate="CopbizValidate.validateMaxLen10"
              field="userName"
              :label="Copbiz.columnTextHTML('이름', '[필수]')"
              type="string"
              width="100px"
              text-align="center"
            />
            <vue-excel-column
              :validate="
                (mobile) => {
                  return CopbizValidate.validateMobileNumber(mobile)
                }
              "
              field="mobile"
              :label="Copbiz.columnTextHTML('휴대폰 번호', '[필수]')"
              type="phone"
              width="208px"
              text-align="center"
            />
          </vue-excel-editor>
        </div>

        <div class="btn">
          <span class="btn-tb">
            <button class="btn-line-lightgray btn-h32-black btn-pad16" @click="deleteAll">
              전체 삭제
            </button>
            <button class="btn-line-lightgray btn-h32-black btn-pad16" @click="deleteSelectedRow">
              삭제
            </button>
          </span>
          <span class="total-register"
            >입력하신 총 건수 <strong>{{ totalCount }}</strong
            >건</span
          >
        </div>
      </div>
    </BaseModalBody>
    <div class="pop-btn">
      <button class="btn-line-lightgray btn-h36-black btn-pad16" @click="isInviteVisible = false">
        취소
      </button>
      <button
        class="btn-solid-primary btn-h36-white btn-pad16"
        @click="submitUsers"
        :disabled="isButtonDisabled"
      >
        초대메일 발송
      </button>
    </div>
  </BaseModal>
</template>

<script setup>

const users = ref(
  Array.from({ length: 100 }, (_, idx) => ({
    idx,
    email: '',
    userName: '',
    mobile: '',
    hasError: false
  }))
)
const grid = ref(null)

const totalCount = computed(() => {
  return users.value.filter((user) => user.email || user.userName || user.mobile).length
})

const emits = defineEmits(['update'])

const handleUpdate = (records) => {
  records.forEach((record) => {
    const user = users.value.find((user) => user.$id === record.$id)
    isPassedValidation(record, user)
    setEssentialFieldError(user)
    checkDuplicateUsers(record)
  })
}

const deleteSelectedRow = () => {
  grid.value.getSelectedRecords().forEach((row) => {
    const deleteTarget = users.value.find((user) => user.$id === row.$id)
    deleteTarget.email = ''
    deleteTarget.userName = ''
    deleteTarget.mobile = ''
    deleteTarget.error = ''
    grid.value.setFieldError('', { $id: deleteTarget.$id }, { name: 'email' })
    grid.value.setFieldError('', { $id: deleteTarget.$id }, { name: 'userName' })
    grid.value.setFieldError('', { $id: deleteTarget.$id }, { name: 'mobile' })
    grid.value.setFieldError('', { $id: deleteTarget.$id }, { name: 'err' })

    // 이메일 중복 검사
    row.name = 'email'
    row.newVal = ''
    checkDuplicateUsers(row)
  })
  grid.value.clearAllSelected()
}

const isPassedValidation = (record, user) => {
  if (record.err !== '') {
    user.hasError = true
  }

  if (record.newVal === '') {
    grid.value.setFieldError('', { $id: record.$id }, { name: record.name })
    user.hasError = false
  }
}
const checkDuplicateUsers = (record) => {
  const emailMap = new Map()

  // users email 중복 입력 map 생성
  users.value.forEach((user) => {
    if (user.email !== '') {
      if (!emailMap.has(user.email)) {
        emailMap.set(user.email, [])
      }
      emailMap.get(user.email).push(user)
    }
  })

  emailMap.forEach((userList) => {
    if (userList.length === 1 && record.newVal === '') {
      grid.value.setFieldError('', { $id: userList[0].$id }, { name: 'email' })
      grid.value.setFieldError(
        CopbizValidate.validateEmail(userList[0].email),
        { $id: userList[0].$id },
        { name: 'email' }
      )
    } else if (userList.length > 1) {
      userList.forEach((user) => {
        grid.value.setFieldError('이메일 중복', { $id: user.$id }, { name: 'email' })
        user.hasError = true
      })
    } else if (record.err === '') {
      userList.forEach((user) => {
        if (user.$id === record.$id && record.name === 'email') {
          grid.value.setFieldError('', { $id: user.$id }, { name: 'email' })
          user.hasError = false
        }
      })
    }
  })
}

const setEssentialFieldError = (user) => {
  if (user.email === '') {
    grid.value.setFieldError('필수 값 누락', { $id: user.$id }, { name: 'email' })
    user.hasError = true
  }
  if (user.userName === '') {
    grid.value.setFieldError('필수 값 누락', { $id: user.$id }, { name: 'userName' })
    user.hasError = true
  }
  if (user.mobile === '') {
    grid.value.setFieldError('필수 값 누락', { $id: user.$id }, { name: 'mobile' })
    user.hasError = true
  }

  if (
    (user.email === '' && user.userName === '' && user.mobile === '') ||
    (CopbizValidate.validateEmail(user.email) === '' &&
      CopbizValidate.validateMaxLen5(user.userName) === '' &&
      CopbizValidate.validateMobileNumber(user.mobile) === '')
  ) {
    grid.value.setFieldError('', { $id: user.$id }, { name: 'email' })
    grid.value.setFieldError('', { $id: user.$id }, { name: 'userName' })
    grid.value.setFieldError('', { $id: user.$id }, { name: 'mobile' })
    user.hasError = false
  }
}

</script>

 

 

에디터에 데이터 입력 시 함수 실행 순서는 다음과 같습니다.

vue3-excel-editor에 입력 -> handleUpdate 실행 -> isPassedValidation 에러 검사 -> setEssentialFieldError 필수 값 검사 ->  checkDupliacateUsers 이메일 중복 검사 

 

 

에디터의 구성요소는 https://github.com/cscan/vue3-excel-editor 에서 찾을 수 있습니다. 예를 들어 에러 값을 설정할 때는 아래 코드와 같이 3가지 파라미터를 넘기면 됩니다. 순서대로 error, row, field를 입력하면 됩니다. 

      grid.value.setFieldError(
        CopbizValidate.validateEmail(userList[0].email),
        { $id: userList[0].$id },
        { name: 'email' }
      )

 

 

 

 

이처럼 많은 옵션들이 제공되는 vue3-excel-editor 였습니다. 다른 옵션, 메서드, 이벤트가 필요한 경우에는 vue3-excel-editor 깃허브에 자세히 나와있습니다.

 

읽어주셔서 감사합니다.

댓글