【Script SetUp】モーダル作成方法【Typescript】

# 始めに
前提条件のコードを添付すると冗長になってしまうため、[こちら](https://qiita.com/tak8_al/items/17b6cdde012cb6a8658d)に書いてあります。
まずは[こちら]()をご覧ください。

# 本記事の内容
本記事は編集用のモーダルの作成を目指したものです。
以下の手順で解説していきます。
* モーダルの作成
* 編集機能の追加

# モーダル作成
①booleanの取得
②メソッドの定義
③モーダルファイルの作成
④buttonとemit

# ①booleanの取得
true,falseでモーダルの開閉を行うため、booleanを作成します。
```vuejs: src/components/todo-lists/editCard.vue
<script setup lang="ts">
import { computed } from 'vue'
import { useStore } from '../../store'

    interface Props {
        list_id: number;
        card_id: number;
        card_description: string;
    }

    const props = defineProps<Props>()

    const store = useStore()
    //booleanを取得
    const isEditable = computed<boolean>(()=>{
        return store.getters['todoLists/getTodoCardById'](props.list_id, props.card_id).isEditable
    })

</script>
<template>
    <div>
        <p>{{props.card_description}}</p>
    </div>
</template>

```
# ②メソッドの定義
* actionsを呼ぶ
* vuexにメソッドを定義

## actionsを呼ぶ
```vuejs: src/components/todo-lists/editCard.vue
<script setup lang="ts">
import { useStore } from '../../store'
  
    //省略

  const store = useStore()
//モーダル開閉のメソッドを定義
const toggleModal = () => {
    store.dispatch('todoLists/toggleEditModal', {
        isEditable: isEditable.value,
        list_id: props.list_id,
        card_id: props.card_id
    })
};
</script>
<template>
    <div>
        <p @click="toggleModal">{{props.card_description}}</p>
    </div>
</template>

```
## vuexにメソッドを定義
```typescript: src/store/todo-lists/index.ts
import { Module, ActionTree, MutationTree, GetterTree } from "vuex";

//型定義
type RootState={
    version: string
}

type TodoListsState = {
    todoLists: TodoList[];
};

type TodoList = {
    id?: number;
    description: string;
};

type TodoCard ={
    id: number;
    pet_name?: string,
    person_name: string,
    description: string;
    isEditable?: boolean;
}
//ローカルストレージ
const savedLists = localStorage.getItem('todo-lists')

export const state: TodoListsState = {
    todoLists: savedLists ? JSON.parse(savedLists): []
};

const getters: GetterTree<TodoListsState, RootState> = {
    getTodoCardById: state => (list_id: number, card_id: number) =>state.todoLists.find(list=>list.id === list_id)!.todoCards.find(card => card.id == card_id)!


const mutations: MutationTree<TodoListsState> = {
    toggleEditModal(state, payload: { isEditable: boolean, list_id: number, card_id: number}){
        const todoCard = state.todoLists.find(list=>list.id === payload.list_id)!.todoCards.find(card => card.id == payload.card_id)!
        todoCard.isEditable = !payload.isEditable
    },
};

const actions: ActionTree<TodoListsState, RootState> = {
    toggleEditModal({commit}, payload: { isEditable: boolean, list_id: number, card_id: number}) {
        commit('toggleEditModal', payload)
    },
}

export const TodoListsModule: Module<TodoListsState, RootState> = {
    namespaced: true,
    state,
    getters,
    actions,
    mutations,
};
```

# ③モーダルファイルの作成
モーダルのテンプレートを書くファイルを作成します。
```vuejs: src/components/todo-lists/EditCardModal.vue
<script setup lang="ts">
</script>

<template>
  <div>
    <teleport to="body">
        <div class="modal" id="sample-modal" v-show="props.isEditable"></div>
            <div class="modal-content" v-show="isEditable">
                <p>編集用モーダルです。</p>
            </div>
    </teleport>
  </div>
</template>

<style scoped>
.modal {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: rgba(0,0,0,.5);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.modal-content {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgba(0,0,0,.5);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    
    background-color: white;
    width: 600px;
    height: auto;
    border-radius: 20px;
    padding: 20px;
}
</style>
```
作成したファイルをeditCardファイルで読み込む
```vuejs: src/components/todo-lists/editCard.vue
<script setup lang="ts">
import { computed } from 'vue'
import { useStore } from '../../store'
import EditCardModal from './EditCardModal.vue' //追記

//省略

</script>
<template>
    <div>
        <p @click="toggleModal">{{props.card_description}}</p>
        <!--追記-->
        <edit-card-modal :isEditable="isEditable" @close="toggleModal" />
    </div>
</template>

```
# ④emit定義
```vuejs: src/components/todo-lists/EditCardModal.vue
<script setup lang="ts">
    import { computed } from 'vue'
    import { useStore } from '../../store'
    
    interface Props {
        isEditable: boolean;
    }

    const props = defineProps<Props>()

    const emitTest = defineEmits(['close'])
</script>

<template>
  <div>
    <teleport to="body">
        <div class="modal" id="sample-modal" v-show="props.isEditable" @click="emitTest('close')"></div>
            <div class="modal-content" v-show="isEditable">
                <p>編集用モーダルです</p>
            </div>
    </teleport>
  </div>
</template>

<style scoped>
//省略
</style>
```

# 編集機能作成
以下の手順で作成します。
①todoCard情報の取得
②vuexにメソッド定義

# ①todoCard情報の取得
取得するために、editCardの方からlist_idとcard_idの情報を渡すことを忘れないでください。

```vuejs: src/components/editCardModal.vue
<script setup lang="ts">
    import { computed } from 'vue'
    import { useStore } from '../../store'
    
    interface Props {
        list_id: number;
        card_id: number;
        isEditable: boolean;
    }

    const props = defineProps<Props>()

    type TodoCard ={
        id: number;
        pet_name?: string,
        person_name: string,
        description: string;
        isEditable?: boolean;
    }

    const emitTest = defineEmits(['close'])

    const store = useStore()
    //取得したいカード情報を取得
    const card = computed<TodoCard>(()=>{
        return store.getters['TodoLists/getTodoCardById'](props.list_id, props.card_id)
    })
    //メソッド定義
    const editCard = () => {
        store.dispatch('TodoLists/editCard', {
            todoCard:{
            id: Math.floor(Math.random() * 100000), 
            person_name: card.value.person_name,
            description: card.value.description
            },
            list_id: props.list_id,
            card_id: props.card_id
        });
    }
</script>

<template>
  <div>
    <teleport to="body">
        <div class="modal" id="sample-modal" v-show="props.isEditable" @click="emitTest('close')"></div>
            <div class="modal-content" v-show="isEditable">
                <form @submit.prevent="editCard">
                    <label>
                        誰が実行するか入力してください。<br>
                        <input type="text" id="description" v-model="card.person_name" /><br>
                    </label>
                    <label>
                        実行するタスクの内容を記載してください。<br>
                        <input type="text" id="description" v-model="card.description" /><br>
                    </label>
                    <input type="submit" value="submit"/>
                </form>
            </div>
    </teleport>
  </div>
</template>

<style scoped>
//省略
</style>
```
# ②Vuexにメソッドの定義
```typescript: src/store/todo-lists/index.ts
import { Module, ActionTree, MutationTree, GetterTree } from "vuex";

//型定義省略

const savedLists = localStorage.getItem('todo-lists')

export const state: TodoListsState = {
    todoLists: savedLists ? JSON.parse(savedLists): []
};

const getters: GetterTree<TodoListsState, RootState> = {
    getTodoCardById: state => (list_id: number, card_id: number) =>state.todoLists.find(list=>list.id === list_id)!.todoCards.find(card => card.id == card_id)!


const mutations: MutationTree<TodoListsState> = {
    editCard(state, payload: {card_id: number,list_id: number, todoCard: TodoCard}){
        const todoList = state.todoLists.find(list=>list.id === payload.list_id)!
        const TodoCard = todoList.todoCards.find(card => card.id == payload.card_id)!
        TodoCard.description = payload.todoCard.description
        TodoCard.person_name = payload.todoCard.person_name
        TodoCard.isEditable = false    
    },
};

const actions: ActionTree<TodoListsState, RootState> = {
    editCard({commit}, payload: {card_id:number, list_id:number, todoCard: TodoCard}) {
        commit('editCard', payload)
    },
}

export const TodoListsModule: Module<TodoListsState, RootState> = {
    namespaced: true,
    state,
    getters,
    actions,
    mutations,
};
```