vue-final / vue-final-modal

🍕Vue Final Modal is a tiny, renderless, mobile-friendly, feature-rich modal component for Vue.js.
https://vue-final-modal.org
MIT License
930 stars 99 forks source link

How to handle reactive props/attrs between parent and child components #429

Open retikaellis opened 9 months ago

retikaellis commented 9 months ago

Version

vue-final-modal: 4.5.3 vue: 3.4.15 nuxt: 3.10.0

Hi! First of all, thank you so much for your work. I'm starting to try the modal in a nuxt 3 app, using useModal(). I don't know if I'm missing something, but I realized the props you pass as attrs are not reactive/are not changing in the child component (ModalConfirm in this case). Here's a code sample. What I'm actually trying to achieve is to change a isLoading boolean prop, so I can show a loading spinner on the confirm button, while making an async request to my API on the onConfirm action.

const modalTitle = ref('')

const { open, close } = useModal({ component: ModalConfirm, attrs: { title: modalTitle.value, onClose() { close() }, onConfirm() { modalTitle.value = "Hello" }, }, slots: { default: "Whatever" }, })

xthree commented 8 months ago

I also need reactive props/attrs.

I think I am going to attempt making a wrapping composable that watches any prop changes and updates the props using the patchOptions function provided by useModal

This is function is demonstrated here https://vue-final-modal.org/api/composables/use-modal

xthree commented 8 months ago

Here's my implementation. Seems to work well. @retikaellis

// reactiveModal.ts
import { useModal, type UseModalOptions } from 'vue-final-modal';

type useReactiveModalOptions = UseModalOptions<any> & {
    attrs: ComputedRef;
};

export const useReactiveModal = (options: useReactiveModalOptions) => {
    const modal = useModal(options);
    const { patchOptions } = modal;

    watch(
        () => options.attrs,
        newVal => {
            patchOptions({ attrs: newVal });
        }
    );

    return modal;
};
Tsyklop commented 3 months ago

Works for me:

const modalProps = reactive<ContentProps>({});

const { open, close} = useModal({
  component: ModalContent,
  attrs: modalProps ,
})

const toggleModalHandler = (data: ContentProps) => {
  modalProps.someProp = data.someProp;
  other props
  open();
};