Home > Mobile >  Passing a value via prop, editing it and saving the new value vue 3
Passing a value via prop, editing it and saving the new value vue 3

Time:01-07

I am trying to pass a value into a child component. The child component will then preform the save operation. The parent doesn't need to know anything about it. I am able to pass in the object but not save its updated form.

Parent

<template>
    <div v-show="isOpened">
        <EditModal @toggle="closeModal" @update:todo="submitUpdate($event)"
            :updatedText="editText" :todo="modalPost" />
    </div>
</template>

<script setup lang="ts">

import Post from "../components/Post.vue";
import { api } from "../lib/api";
import { ref } from "vue";
import { onMounted } from "vue-demi";
import EditModal from "../components/EditModal.vue";

const postArr = ref('');
const message = ref('');
let isOpened = ref(false);
let modalPost = ref('');
let editText = ref('');

function closeModal() {
    isOpened.value = false
}
function openModal(value: string) {
    isOpened.value = true
    modalPost.value = value
}

// call posts so the table loads updated item
function submitUpdate(value: any) {
    console.log("called update in parent  "   value)
    editText.value = value
    posts()
}
</script>

Child EditModal

<template>
    <div>
        <div>
            <textarea id="updateTextArea" rows="10" :value="props.todo.post"></textarea>
        </div>
    
        <!-- Modal footer -->
        <div>
            <button data-modal-toggle="defaultModal" type="button"
                @click="update(props.todo.blogId, props.todo.post)">Save</button>
        </div>
    </div>
</template>

<script lang="ts" setup>
import { api } from "../lib/api";
import { reactive, ref } from "vue";

const props = defineProps({
todo: String,
updatedText: String,
})

const emit = defineEmits(
['toggle','update:todo']
);

function setIsOpened(value: boolean) {
emit('toggle', value);
}

function update(id: string, value: string) {
console.log('the value   '   value)
try {
api.updateBlog(id, value).then( res => {
emit('update:todo', value)
emit('toggle', false);
})
} catch (e) {
console.log('Error while updating post: '  e)
}

}
</script>

I know the props are read only, therefore I tried to copy it I can only have one model. I do not see the reason I should $emit to the parent and pass something to another variable to pass back to the child. I am trying to pass in text to a modal component where it can edit the text and the child component saves it.

Advice?

CodePudding user response:

First, your component should be named EditTodo no EditModal because you are not editing modal. All Edit components should rewrite props to new local variables like ref or reactive, so you can work on them, they won't be read only any more.

Child EditTodo.vue

<template>
    <div>
        <div>
            <textarea id="updateTextArea" rows="10" v-model="data.todo.title"></textarea>
        </div>
        <div>
            <button data-modal-toggle="defaultModal" type="button" @click="update()">Save</button>
        </div>
    </div>
</template>

<script setup lang="ts">
import { api } from "../lib/api";
import { reactive } from "vue";

const props = defineProps<{ id: number, todo: { title: string} }>()
const emit = defineEmits(['toggle']);

const data = reactive({ ...props })

// I assuming api.updateBlog will update data in database
// so job here should be done just need toogle false modal
// Your array with todos might be not updated but here is
// no place to do that. Well i dont know how your API works.
// Database i use will automaticly update arrays i updated objects
function update() {
    try {
        api.updateBlog(data.id, data.todo ).then(res => {
            emit('toggle', false);
        })
    }
}
</script>

Parent

<template>
    <div>
        <BaseModal v-if="todo" :show="showModal">
            <EditTodo :id="todo.id" :todo="todo.todo" @toggle="(value) => showModal = value"></EditTodo>
        </BaseModal>
    </div>
</template>

<script setup lang="ts">

const showModal = ref(false)

const todo = reactive({ id: 5, todo: { title: "Todo number 5"} })

</script>

I separated a modal object with edit form, so you can create more forms and use same modal. And here is a simple, not fully functional modal.

<template>
   <div ><slot></slot></div>
</template>

<script setup>
defineProps(['show'])
defineEmits(['toogle'])
</script>

You might want to close modal when user click somewhere outside of modal.

  • Related