Question T14531
Visible to All Users

Custom widget for file upload question does not record the new description data field value

created a year ago

Dear Support,

When adding a new data field to a file upload question using a widget the value for the new data field is only recorded/saved when the value of the uploaded file has changed but not when I only change the value of the new data field.

  1. I created a new widget to add a new data field (description) to the file upload question.
  2. The value for the new data field (description) is only recorded when the upload file has changed.

Question: How do I ensure that when only the value of the new data field (description) has changed this new value is recorded.

See below the afterRender of the widget and attached the new/updated file upload question.

Thanks,

Eric

JavaScript
afterRender: function (question, el) { var setDescription = false; var mainDiv = document.createElement("div"); var fileDescription = document.createElement("INPUT"); fileDescription.id = "fileDescription_id"; fileDescription.name = "fileDescription_id"; fileDescription.type = "text"; fileDescription.style.cssText = "background-color: #f9f9f9;"; var fileDescriptionLabel = document.createElement("Label"); fileDescriptionLabel.htmlFor = "fileDescription_id"; fileDescriptionLabel.innerHTML="Description"; mainDiv.appendChild(fileDescriptionLabel); mainDiv.appendChild(fileDescription); el.parentElement.insertBefore(mainDiv, el); // fileDescription.onchange does not have the desired effect to change the question description value fileDescription.onchange = function () { for (let index = 0; index < question.value.length; index++) { question.value[index].description = fileDescription.value; } }; var onValueChangedCallback = function () { if(setDescription == false) { if(typeof question.value[0].description == 'undefined') { fileDescription.value = ''; } else { fileDescription.value = question.value[0].description; } setDescription = true; } else { for (let index = 0; index < question.value.length; index++) { question.value[index].description = fileDescription.value; } } for (let index = 0; index < question.value.length; index++) { if(typeof question.value[index].description == 'undefined') { question.value[index].description = ''; } } } question.valueChangedCallback = onValueChangedCallback; },
Show previous comments (1)

    Hi Jane,

    I am using Knockout.

    Eric

      Thank you for the clarification, Eric. To help me follow, would you please share a simplified demo which reproduces the issue?

      I look forward to your reply.

        Hi Jane,

        Find the link: Sandbox

        In the preview, when uploading a file in the file upload question it will show the description data field. After giving a value to the description data field it will not save this value when completing the survey. How can I save the value for the description data field.

        Thanks,

        Eric

        Answers approved by surveyjs Support

        created a year ago (modified 2 months ago)

        Hello Eric,
        Thank you for sharing the demo.

        A custom description field is not saved within survey.data because the description property is not serializable. However, the file item description property value is actually stored within survey results. You can access it using the survey.getPlainData function. The getPlainData function contains detailed information about survey objects and their values.

        JavaScript
        creator.onSurveyInstanceCreated.add((sender, options) => { if (options.reason === "test") { options.survey.onComplete.add((sender, options) => { let fileQuestionValue = sender.getPlainData()[0].data[0]; let fileDescription = fileQuestionValue.description; //... }); } });

        However, I believe that the most optimal option would be to build a custom array of survey results from survey data: Modify Survey Results.

        Please consider the following code:

        JavaScript
        creator.onSurveyInstanceCreated.add((sender, options) => { if (options.reason === "test") { options.survey.onComplete.add((sender, options) => { const resultData = []; for (const key in sender.data) { const question = sender.getQuestionByName(key); if (!!question) { const item = { name: key, }; // Generate an array of file item values from a File question if (question.getType() === "file") { item.value = []; question.value.forEach((fileItem) => { item.value.push({ fileName: fileItem.name, fileType: fileItem.type, contents: fileItem.content, description: fileItem.description, }); }); } else { // For regular questions, simply use a value item.value = question.value; } resultData.push(item); } } console.log(JSON.stringify(resultData, null, 3)); }); } });

        I updated your example to demonstrate this: View Demo.

        A sample output would be:

        JSON
        [ // A regular Text input { "name": "question1", "value": "some text" }, // A File question { "name": "fileupload", "value": [ { "fileName": "PRO.png", "fileType": "image/png", "contents": "data:image/png;base64,...", "description": "Sample Description" } ] } ]

        I hope this helps. Should you have any further questions, I'm here to help.

          Show previous comments (1)

            Hi Eric,
            Please accept my apologies for the delayed reply. I'm happy to hear that you found another solution. To preserve a file description, I may also recommend that you create a new variable/constant before the for loop and assigns the value of question.value to this new constant. After the loop, set question.value to the modified qValue array. Now, any changes made inside the loop to the elements of qValue will be reflected in the question.value variable.

            JavaScript
            fileDescription.onchange = function () { const qValue = question.value; for (let index = 0; index < qValue.length; index++) { qValue[index].description = fileDescription.value; } question.value = qValue; };

            View Demo

            With this option, a file description will be saved within survey.data.

            Let me know if you have any further questions.

              Hi Jane,

              Sorry for the late reply, this is exactly what I was looking for!!!

              Thanks for the solution,

              Eric

                You're very welcome, Eric. Please feel free to contact us if you have any further questions.