formkit / drag-and-drop

https://drag-and-drop.formkit.com
MIT License
1.45k stars 28 forks source link

How to handle dragAndDrop with global state, pinia store or useState nuxt? #38

Open carlosvaldesweb opened 7 months ago

carlosvaldesweb commented 7 months ago

Hello, i'm working with Nuxt 3 and useState in composable called useQuiz, i'm using deep components and i need to work with global state, the quiz variable has the follow structure:

export type Question = {
  id: string;
  quiz_id: number;
  question_type: QuestionType;
  question: string;
  description: string;
  time_limit: number;
  score: number;
  image: File;
  order: number;
  feedback: string;
  allows_multiple_answers: boolean;
  active: boolean;
  options: QuestionOption[];
};

export type Quiz = {
  id: number;
  user_id: number;
  course: Course;
  language: Language;
  text: TextResponse;
  title: string;
  description: string;
  slug: string;
  max_score: number;
  pass_score: number;
  questions: Question[];
  created_at: string;
};

Now i need to pass Quiz.value.questions and also after in another component i need to pass quiz.value.question.options, how can i handle?

I'm trying to to this, but i can't because i need to pass type Ref, but i can't because i lose the reactivity when i add a new item to quiz.questions or when i remove a question.

const { fetchQuiz, quiz, reOrderQuestion, moveQuestion } = useQuiz();
const { fetchQuestionTypes } = useQuestionTypes();
const { pending } = await useAsyncData(async () => {
  return await Promise.all([
    fetchQuiz(route.params.id as string),
    fetchQuestionTypes(),
  ]);
});
const parentRef = ref<HTMLElement | undefined>(undefined);

dragAndDrop({
  parent: parentRef,
  values: quiz.value?.questions,
});
xlanex6 commented 5 months ago

Hi @carlosvaldesweb

I find a dirty solution, to update my pinia store

const shopStore = useShops()
const { updateImplementation, loadRack, loadRackForced } = shopStore
const { selectedShop } = storeToRefs(shopStore)

const [
  parent,
  racks] =
  useDragAndDrop(selectedShop.value.implementation, {
    draggingClass: 'bg-blue-800 text-white',
    handleEnd: ({ targetData }) => {
      const newOrderedArrValue = targetData.parent.data.enabledNodes.map(({ data }) => data.value) 
      selectedShop.value.implementation = newOrderedArrValue
      updateImplementation()
    },
    sortable: true,
  });

if it could help OR If you're already find a better option , let me knows

dominikklein commented 3 months ago

Yes usage of an reactive value (ref/computed) is a common situation or?

E.g. a list from the server with a subscription behind which adds additional things.

sashamilenkovic commented 3 months ago

@dominikklein Sure! I would suggest taking whatever ref (from Pinia store, within your component's setup script, or wherever else) you have and passing it specifically to the dragAndDrop function call (not useDragAndDrop as that returns a reactive value for you).

I'd be happy to look at a reproduction if you get blocked.

sashamilenkovic commented 3 months ago

@xlanex6 In your example, if you used the dragAndDrop hook instead you could pass your reactive value directly without having to worry overriding the handleEnd method to update the value in your store.