VueJS/Nuxt

[VueJS] NuxtJS+Vuetify confirm 컴포넌트 만들어보기

SongMinu 2021. 9. 26. 14:36
728x90

alert도 컴포넌트로 만들어본 김에 confirm도 만들어봤다.

https://minu0807.tistory.com/99

 

[VueJS] NuxtJS+Vuetify alert 컴포넌트 만들어보기

nuxt와 vuetify를 이용해 프로젝트를 만들면서 alert 창을 띄우다 보니 기본 alert 창이 보기가 너무 싫었다. vuetify에서 제공하는 컴포넌트를 이용해서 만들어보면 괜찮지 않을까? 하는 생각으로 만들

minu0807.tistory.com

사용 방식을 다르게 만들었는데, 이유는 confirm은 확인이냐 취소냐 누른 후에 다음 로직으로 진행해야 하기 때문에

alert처럼 vuex방식이 아니라 부모에서 자식 컴포넌트로 접근하는 방식으로 처리했다.

https://minu0807.tistory.com/94

 

[VueJS] 부모 컴포넌트에서 자식 컴포넌트 함수 실행

부모 컴포넌트에서 자식 컴포넌트의 props에 맞춰 데이터를 넘기다 부모에서 자식 컴포넌트 안에 있는 함수를 실행을 할 수는 없을까? 하고 찾아보았는 데 있었다... 아직 모르는 게 너무 많은 듯

minu0807.tistory.com

그리고 컴포넌트 실행 후 결과를 받아오는 걸 기다려야하기 때문에 promise 함수를 이용해 처리했다.


먼저 confirm 컴포넌트 소스

<template>
  <v-overlay
    :value="is_show"
    z-index="100005"
    >
    <v-alert :type="type" border="right" colored-border>
      <v-row>
        <v-col cols="12">
          {{ title }}
        </v-col>
        <v-col cols="12" v-html="change(text)">
        </v-col>
      </v-row>
      <v-row >
        <v-col cols="12" align="end">
          <v-btn
            :color="type"
            @click="ok"
            >
              예
            </v-btn>
          <v-btn
            text
            outlined
            @click="cancel"
            >
              아니요
            </v-btn>
        </v-col>
      </v-row>
    </v-alert>
  </v-overlay>
</template>

<script>
export default {
  data() {
    return {
      is_show: false,
      type: 'info', //success, info, warning, error 이렇게 4가지 사용 가능
      title: '',
      text: '',
      result : undefined,
    }
  },
  mounted() {
    document.addEventListener('keydown', this.onKeyEvent);
  },
  methods:{
    onKeyEvent(e) {
      if (this.is_show) {
        let code = e.keyCode;
        console.log(code);
        if (code === 27) { //esc
          this.cancel();
        } else if (code === 13) { //enter
          this.ok();
        } else {
          e.stopPropagation();
          e.preventDefault();
        }
      }
    },
    change(v) {
      return String(v).replace(/(?:\r\n|\r|\n)/g,"</br>");
    },
    open (options) {
      this.is_show = true;
      this.type = options.type === (null || '') ? 'info' : options.type;
      this.title = options.title;
      this.text = options.text;
      return new Promise( (resolve, reject) => {
        this.result = resolve;
      })
    },
    ok() {
      this.is_show = false;
      this.result(true);
    },
    cancel() {
      this.is_show = false;
      this.result(false);
    }
  }
}
</script>

<style>

</style>

사용 방식은 부모에서 이 컴포넌트의 open 함수을 실행시키면 confirm 창이 열린다.

open 함수를 실행 시킬 때 컴포넌트에 띄울 title, text와 컴포넌트의 타입 이렇게 3가지를 넣어서 보내주면 된다.

그리고 promise를 쓰면 될 것 같은 건 알았는데,

open을 실행 하면서 컴포넌트를 띄우고 저기서 어떻게 해야 다른 함수인 확인과 취소 버튼을 눌러서 resolve를 보낼 수 있을지는 구글링 해보니 저런 방식으로 처리 가능하다는 걸 찾아서 해보니 됐다.

 

이제 사용 예시 소스

<template>
  <v-layout column>
    <confirm ref="cf" />
    <v-flex class="ma-4">
      <v-row>
        <v-col cols="12">
          <v-card>
            <v-card-title>confirm 컴포넌트 만들어보기</v-card-title>
            <v-card-text>
              <v-btn @click="go">confirm go!</v-btn>
            </v-card-text>
          </v-card>
        </v-col>
      </v-row>
    </v-flex>

  </v-layout>
</template>

<script>
import confirm from '~/components/custom/confirm'
export default {
  components: {
    confirm
  },
  methods:{
    async go() {
      console.log('go!');
      const rs = await this.$refs.cf.open({
        type:'success',
        title: 'Confirm!!',
        text: 'Ok??\nChoice Button!'
      });
      if (rs) {
        console.log('true!!!');
      } else {
        console.log('false!!!');
      }
    }
  }
}
</script>

<style>

</style>

사용하고자 하는 컴포넌트에서 import를 한 후 접근을 위해 ref 값을 넣어주어야 한다. (3번 라인)

그리고 버튼에 지정된 함수 go를 확인해 보면, confirm 컴포넌트에서 open을 promise 함수로 만들었기 때문에 async/await을 사용했다.

그리고 화면에 출력할 type, title, text를 넘겨주면 된다.

 

결과 화면

CONFIRM GO! 버튼을 눌러서 출력된 화면이다.

type은 success, info, warning, error 이렇게 4가지를 쓸 수 있고, 출력되는 모습은 다음과 같다.

type : info
type : warning
type : error

그리고 위 소스에서 보면 알 수 있듯이, 예를 누르면 true를 반환하고, 아니오를 누르면 false를 반환한다.

반응형