오늘의 해야할 일
이거를
이렇게 만들어야 한다.
어떻게해야하나.
- 헤더에 버튼을 추가할 컬럼을 추가해야한다.
- slot 을 이용하여 추가 컬럼을 넣는다.
- 라익디스
슬롯이랑 컬럼 명을 매핑시켜주면 된다.
일단 버튼은 만들었다.
다음은 버튼에 이벤트를 넣어야 한다.
이벤트는 컴포넌트 기준으로 아래와 같이 동작한다.
Button(v-btn) → DataTable(v-data-table-server) → page
처음에는 Button 컴포넌트에 props으로 클릭 이벤트 함수를 전달하여 구현하고자 했는데,
생각해보니 @click 디렉티브는 이벤트 버블링의 규칙이 적용되므로 굳이 함수로 전달하는 과정이 필요하지 않았다.
그냥 상위 컴포넌트에서 @click 디렉티브를 사용하여 이벤트를 구현하면, 자연스럽게 클릭 이벤트를 핸들링 할 수 있다.
물론, dataTable에서 클릭 이벤트가 일어나더라도 페이지에서 클릭 이벤트가 일어나는것은 아니므로,
해당 클릭 이벤트를 감지하여 커스텀 이벤트로 emit해주어야 한다.
이런식으로 클릭할때 이벤트를 호출하고 다이어로그를 띄울 수 있다.
<Dialog
:dialogTitle="actionFlag ? '새 항목 추가' : '항목 수정'"
:showDialog="showDialog"
@update:showDialog="showDialog = $event"
>
<template #content>
<item-action
@close="showDialog = false"
:actionFlag="handleItemAction"
/>
</template>
</Dialog>
const handleItemAction = (item: any) => {
console.log(item);
actionFlag.value = false;
showDialog.value = true;
};
단, item(row)에 따라 각 row의 고유한 id를 dialog에 전달해줘야만 수정할 수 있도록 작성할 수 있다.
item-action 팝업에 추가적인 props가 필요하다.
partner_email_id는 선택적으로 제공해야 하는 props인데 현재 사용중인 defineProps로는 코드가 너무 관리하기 귀찮았다.
import { defineProps } from 'vue';
const props = defineProps({
actionFlag: {
type: Boolean,
default: false,
},
emailId: {
type: String,
default: "",
required: false, // 선택적인 props 지정
},
});
이건 vue에서만 쓰는 패턴이므로 기존에 사용하는 type 정의 패턴과 달라 나중에 읽고 사용하기 불편할 것 같았다.
찾아보니 아래와 같이 사용할 수 있었다.
const props = defineProps<{
addMemberFlag: boolean;
partner_email_id?: string; // 선택적인 프로퍼티
}>();
그런데 이렇게하면 초기값을 줄 수가 없다.
그래서 또 찾아보니
const props = withDefaults(
defineProps<{
addMemberFlag: boolean;
partner_email_id?: number;
}>(),
{
addMemberFlag: false,
partner_email_id: 0,
}
);
이렇게 사용할 수 있었다.
그런데 dialog가 오픈할때 해당 row의 모든 데이터를 셋팅해주어야 한다.
우습게도 텍스트필드 컴포넌트를 만들면서 v-model이 정상적으로 동작하는지에 대한 테스트를 안했었는데,
생각보다 복잡했다.
// 부모
<TextField
v-model="email"
placeholder="example@atommerce.com"
label=""
:rules="emailRules"
/>
// 자식
const props = defineProps({
modelValue: {
type: String,
default: "",
},
...
const emit = defineEmits(["update:modelValue"]);
컴포넌트가 위와 같을때,
부모 컴포넌트와 자식 컴포넌트간의 양방향 바인딩을 위해서는 props에 **modelValue 를 추가해줘야 한다.
(당연하지만 이름은 딱히 관계없음)
<template>
<div>
<v-text-field
...
v-model="maskedInput"
@input="handleInput"
...
>
<template v-slot:append-inner>
<span v-if="helperText">{{ helperText }}</span>
</template>
</v-text-field>
</div>
</template>
const maskedInput = computed({
get() {
return props.modelValue;
},
set(value) {
let resultValue = value;
emit("update:modelValue", resultValue);
},
});
const handleInput = (value) => {
emit("update:modelValue", value);
};
이런식으로 computed를 사용하는 경우에 작성할 수 있다.
추가로 props를 해당 페이지에서 사용하는 ref에 초기화한다.
const email = ref(props.item ? props.item["email"] : "");
const gender = ref(props.item ? String(props.item["gender"]) : "");
이제 데이터를 화면에서 볼 수 있다.
저장하기 위해 코드를 아래와 같이 분기처리한다.
const registerOrUpdate = () => {
console.log("Action initiated");
const genderKey = gender.value === "1" ? 1 : gender.value === "2" ? 2 : 0;
if (props.item && props.item.id) {
// 수정
const { execute, response } = useUpdateItem({
id: uniqueId, // 고유 식별자를 사용
itemId: props.item.id,
email: email.value,
department: department.value,
position: position.value,
gender: genderKey,
birthYear: birthYear.value,
});
execute().then(() => {
serverResponseToasts({
successText: "Item successfully updated.",
response: response.value,
});
if (response.value.errors.length === 0) {
emit("close");
}
});
} else {
// 등록
const { execute, response } = useRegisterItem({
id: uniqueId, // 고유 식별자를 사용
email: email.value,
department: department.value,
position: position.value,
gender: genderKey,
birthYear: birthYear.value,
});
execute().then(() => {
serverResponseToasts({
successText: "Item successfully registered.",
response: response.value,
});
if (response.value.errors.length === 0) {
emit("close");
}
});
}
};
저장끝
'오늘의 커밋' 카테고리의 다른 글
230817 nuxt에서 빠르게 기능 추가하기(안빠름) (0) | 2023.08.17 |
---|---|
230816 nuxt에서 quillJS 이용하여 텍스트에디터 기능 구현하기 (0) | 2023.08.17 |
22.02.14 랜섬웨어에 걸리다. (0) | 2022.02.23 |
docker 튜토리얼 (0) | 2021.12.09 |
2021.04.13 오늘의 커밋. 크롬에서 dragEnter 이슈 (0) | 2021.04.13 |