LoginSignup
9
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-10-28

始めに

前提条件のコードを添付すると冗長になってしまうため、こちらに書いてあります。
まずはこちらをご覧ください。

本記事の内容

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

  • モーダルの作成
  • 編集機能の追加

モーダル作成

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

①booleanの取得

true,falseでモーダルの開閉を行うため、booleanを作成します。

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を呼ぶ

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にメソッドを定義

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,
};

③モーダルファイルの作成

モーダルのテンプレートを書くファイルを作成します。

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ファイルで読み込む

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定義

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の情報を渡すことを忘れないでください。

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にメソッドの定義

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,
};
9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2