surveyjs / survey-library

Free JavaScript form builder library with integration for React, Angular, Vue, jQuery, and Knockout.
https://surveyjs.io/form-library
MIT License
4.02k stars 783 forks source link

Store a full choice object within survey results #7869

Open JaneSjs opened 4 months ago

JaneSjs commented 4 months ago

Updated:

Suggested API:

const data = survey.getQuestionsValues((question: Question, value: any): any => {
  if(question.isDescendantOf("checkbox")) {
   const res = [];
   question.selectedItems.forEach(item => res.push({ id: item.value, text: item.text }));
  return res;
 } else {
    if(question.isDescendantOf("selectbase")) {
      const item = question.selectedItem;
      return { id: item.value, text: item.text };
   }
 }
 return value;
});

The function will call the callback function that is passed as a parameter for all questions including matrix cell questions, inside dyanamic panels and composite components.


T16847 - Store full object for Dropdown, Multi Checkboxes questions https://surveyjs.answerdesk.io/internal/ticket/details/T16847


Currently, survey.data contains selected choice values in the following format:

 "question2": [
        "i1",
        "i2"
    ],

Introduce an option to store the entire choice object ({ value: XXX, text: YYY} or { id: XXX, text: YYY }) within survey results. An example of a required output format:

 {
      "name": "question1",
      "value": [
         {
            "id": "i1",
            "text": "Item 1"
         },
         {
            "id": "i2",
            "text": "Item 2"
         }
      ]
   },

In the meantime, it can be achieved by generating a custom response object within the survey.onComplete function: View Plunker.

 function createChoiceAnswer(question, resultData){
        if(Array.isArray(question.value)) {
                    const item = {
                        name: question.name,
                        value: []
                    };
                    question.value.forEach((choiceValue) => {
                        const choice = Survey.ItemValue.getItemByValue(
                            question.choices,
                            choiceValue
                        ); 
                        item.value.push({
                            id: choice.value,
                            text: choice.text
                        });
                    });
                    resultData.push(item);   
                } else {
                    const choice = Survey.ItemValue.getItemByValue(
                            question.choices,
                            question.value
                        ); 
                    const item = {
                        name: question.name,
                        value: {
                            id: choice.value,
                            text: choice.text
                        }
                    };
                    resultData.push(item);   
            }
    }
   survey.onComplete.add((survey) => {
        const resultData = [];
        for (const key in survey.data) {
            const question = survey.getQuestionByName(key);

            const qType = question.getType();
            switch(qType) {
                case "paneldynamic": 
                    // Generate a panel dynamic answer
                    const dynamicQuestionAnswer = [];

                    let panelAnswers = [];
                    question.value.forEach((panelValue) => {
                        panelAnswers = [];
                        for (const key in panelValue) {
                            const allPanelQestions = question.getNestedQuestions();
                            const targetQuestion =                       allPanelQestions.filter(q => q.name === key)[0];
                            if(!!targetQuestion.choices){
                                createChoiceAnswer(targetQuestion, panelAnswers);
                            } else {
                                // Create a simple question answer
                                const item = {
                                    name: key,
                                    value: targetQuestion.value
                                };
                                panelAnswers.push(item);
                            }
                        }
                        dynamicQuestionAnswer.push({
                            value: panelAnswers
                        })
                    });
                    const dynamicQuestionReply = {
                        name: question.name,
                        value: dynamicQuestionAnswer
                    }
                    resultData.push(dynamicQuestionReply);
                break;
                case "matrixdynamic": 
                debugger
                     // Generate a matrix dynamic answer
                    const dynamicMatrixAnswer = [];

                    let matrixRowAnswers = [];
                    question.value.forEach((panelValue) => {
                        matrixRowAnswers = [];
                        for (const key in panelValue) {
                            const allPanelQestions = question.getNestedQuestions();
                            const targetQuestion =                       allPanelQestions.filter(q => q.name === key)[0];
                            if(!!targetQuestion.choices){
                                createChoiceAnswer(targetQuestion, matrixRowAnswers);
                            } else {
                                // Create a simple question answer
                                const item = {
                                    name: key,
                                    value: targetQuestion.value
                                };
                                matrixRowAnswers.push(item);
                            }
                        }
                        dynamicMatrixAnswer.push({
                            value: matrixRowAnswers
                        })
                    });
                    resultData.push({
                        name: question.name,
                        value: dynamicMatrixAnswer
                    });

                break;
                default:
                    if(!!question.choices){
                        createChoiceAnswer(question, resultData);
                    } else {
                        // Create a simple question answer
                        const item = {
                            name: key,
                            value: question.value
                        };
                        resultData.push(item);
                    } 
            }
        };
      console.log(JSON.stringify(resultData, null, 3));
});
JaneSjs commented 2 months ago

I updated the demo with the purposed API: View Plunker.

function getValue(question){
        if(question.isDescendantOf("checkbox")) {
        const res = [];
        question.selectedItems.forEach(item => res.push({ id: item.value, text: item.text }));
        return res;
        } else {
            if(question.isDescendantOf("selectbase")) {
            const item = question.selectedItem;
            return { id: item.value, text: item.text };
        }
        }
        return value;
    };

   survey.onComplete.add((survey) => {
        const resultData = [];
        for (const key in survey.data) {
            const question = survey.getQuestionByName(key);
            if (!!question) {
            if(!!question.choices){
                const item = {
                        name: question.name,
                        value: []
                };
                item.value = getValue(question);
                resultData.push(item);   
            } else {
                const item = {
                    name: key,
                    value: question.value
                };
                resultData.push(item);
                }
            }
        }
      // Send data to a storage
      console.log(JSON.stringify(resultData, null, 3));
    });