vue-flow-form icon indicating copy to clipboard operation
vue-flow-form copied to clipboard

Skip to submit page

Open moranje opened this issue 1 year ago • 6 comments

This may be feature request, at this point I just want to know whether it's possible. What I'm trying to do is create a way to skip to the submit page of the form. I have a question (actually) a few that should lead the user to finish quick. The information they require will be on the submit page.

To make things more interesting, whether or not the jump should happen depends on multiple questions. The wat I'm handling that is an onAnswered method that has access to the questionList via this.$refs. There are no required questions.

...
onAnswer(question) {
  if (question.id === 'riskAssessment') {
    if (
      this.$refs.flowform.questionList[1].answer === 'tissueInvasion' &&
      this.$refs.flowform.questionList[2].answer === 'pregnant'
    ) {
      this.$refs.flowform.goToQuestion('_submit'); // <-- this does't work
      // this.$refs.flowform.goToQuestion(5); <-- this, doesn't work either (questionList has a length of 5)
    }
  }
}
...

From what I can gather in the code there isn't an api call to mark the form 'complete'. Is that right?

If that's right it can either be implemented by giving jump functions (which can jump to submit right) access to a read-only version of questionList (so as no to mess with the vue reactivity) or a public API call that mark the form a 'complete' and jumps to the last page. What method would be preferred?

moranje avatar Jul 26 '22 05:07 moranje

Hi @moranje,

this is actually an oversight in the goToQuestion method, but there is a way around it - the jump parameter of each question can be a function callback.

https://www.ditdot.hr/en/docs/vue-flow-form-guide#global-options

This means you can define your riskAssessment question jump as a callback and do your logic there (return _submit when you want to jump to the end, and the ID of the next question otherwise).

spinn avatar Jul 26 '22 08:07 spinn

Hi @moranje,

this is actually an oversight in the goToQuestion method, but there is a way around it - the jump parameter of each question can be a function callback.

https://www.ditdot.hr/en/docs/vue-flow-form-guide#global-options

This means you can define your riskAssessment question jump as a callback and do your logic there (return _submit when you want to jump to the end, and the ID of the next question otherwise).

I tried that, but I only seem to have access to the current question model. I need access to multiple question models. Or am I missing something?

moranje avatar Jul 26 '22 10:07 moranje

You always have access to all the question models, although the way to access them depends on how you defined them in the first place. Our questionnaire and quiz examples define questions through the data object which you can access with this.questions. The support page uses questions as components, but the base definitions are still in the data object and still accessible via this.questions.

How are you defining your questions?

spinn avatar Jul 26 '22 10:07 spinn

Agh, that must be it then. I started out with the intention of splitting out each question as a separate component file. The logic got more complicated then I wanted so I switched to separate components inside the form accidentally isolating the questions from the others. Like this.

// inside template 
<flow-form ref="flowform" :language="language" v-on:answer="onAnswer">
    <question
      id="riskAssessment"
      title="Behoort patiënt tot een risicogroep"
      type="multiplechoice"
      nextStepOnAnswer
      :options="riskAssessment.options"
      :jump="riskAssessment.jump"
      required
      v-model="riskAssessment.model"
    />
</flow-form>

// inside script data property
riskAssessment: {
  options: [
    new ChoiceOption({
      label: 'Nee',
      value: 'healthy',
    }),
    new ChoiceOption({
      label: 'Diabetes mellitus of een verminderde weerstand',
      value: 'vulnerable',
    }),
    new ChoiceOption({
      label: 'Zwangeren',
      value: 'pregnant',
    }),
    new ChoiceOption({
      label: 'Mannen',
      value: 'men',
    }),
    new ChoiceOption({
      label: 'Kinderen',
      value: 'children',
    }),
  ],
  jump() {
    console.log('Jump', this); // <-- Only has access to this questions model
    if (this.answer === 'children') return 'antibiotics';
  },
  model: {},
}

Back to the drawing board, I'll let you know whether it works.

moranje avatar Jul 26 '22 11:07 moranje

Nope, I'm lost. Can't access the questions list inside a jump. The code only binds a questions model I think:

https://github.com/ditdot-dev/vue-flow-form/blob/0a6d282abd3ce053891564c57426fabf2c6e5f2f/src/models/QuestionModel.js#L174

I'll copy over the entire vue file for clarity, maybe I'm still doing something wrong;

<template>
  <flow-form ref="flowform" :language="language" v-on:answer="onAnswer">
    <template v-slot:complete>
      <advice-page />
    </template>

    <question
      v-for="(question, index) in questions"
      v-bind="question"
      v-bind:key="'m' + index"
      v-model="question.model"
    >
    </question>
  </flow-form>
</template>

<script lang="ts">
  import {
    FlowForm,
    LanguageModel,
    Question,
    ChoiceOption,
  } from '@ditdot-dev/vue-flow-form';
  import AdvicePage from './AdvicePage.vue';

  export default {
    name: 'FormMain',

    components: {
      FlowForm,
      AdvicePage,
      Question,
    },

    data() {
      return {
        questions: [
          {
            type: 'multiplechoice',
            id: 'riskAssessment',
            title: 'Behoort patiënt tot een risicogroep?',
            multiple: false,
            nextStepOnAnswer: true,
            required: true,
            jump() {
              console.log('Jump', this); // This doesn't have access to the questionsList
            },
            options: [
              {
                label: 'Nee',
                value: 'healthy',
              },
              {
                label: 'Diabetes mellitus of een verminderde weerstand',
                value: 'vulnerable',
              },
              {
                label: 'Zwangeren',
                value: 'pregnant',
              },
              {
                label: 'Mannen',
                value: 'men',
              },
              {
                label: 'Kinderen',
                value: 'children',
              },
            ],
            model: {},
          },
        ],
      };
    },

    methods: {
      onAnswer(question) {
        console.log('Flowform data', this.$refs.flowform, question);

        if (question.id === 'riskAssessment') {
          if (
            this.$refs.flowform.questionList[1].answer === 'tissueInvasion' &&
            this.$refs.flowform.questionList[2].answer === 'pregnant'
          ) {
            console.log('Tissue invasion in pregnancy');

            this.$refs.flowform.goToQuestion(4);
          }
        }
      },
    },
  };
</script>

moranje avatar Jul 26 '22 12:07 moranje

Ah I see you mean IF I use an arrow function THEN I'll have access to the component scope. I dare say it's not completely obvious. For those entering the same pitfall:

// This doesn't work as you will only get access to the current questions model
jump() {
  console.log('Jump', this);
  if (this.answer === 'children') return 'antibiotics';
}

// However since an arrow function is basically the same as binding the current scope (vue component scope)
// you do get access to the questions array.
jump: () => {
  console.log('Jump', this); // refers to vue component scope
  if (this.questions[1].model === 'children') return 'antibiotics';
}

Hope this helps someone

moranje avatar Jul 26 '22 18:07 moranje