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.2k stars 810 forks source link

Disappearing survey content when switching to `singlePage` mode before printing #4637

Closed schlick closed 2 years ago

schlick commented 2 years ago

Are you requesting a feature, reporting a bug or asking a question?

Bug

What is the current behavior?

As part of a print all questions custom behaviour, when switching to singlePage mode prior to calling window.print(), all the survey content disappears resulting no questions appearing in the print dialog.

Standard page

Screen Shot 2022-07-25 at 1 29 06 pm

Page disappears prior to printing

Screen Shot 2022-07-25 at 1 28 55 pm

What is the expected behavior?

When switching to singlePage mode prior to calling window.print(), all the survey content is displayed in a single page.

I expect this is not a bug but a change in behaviour and that I would need to change my custom code to accommodate this change in behaviour.

How would you reproduce the current behavior (if this is a bug)?

Using the test code, click the Print All Questions button.

The expected behaviour works with surveyjs v1.8.21. Starts to change with v1.8.22 where the page and question titles disappears and then the whole page disappears starting with v1.8.37

I've also added two extra buttons to the test page, Single Page and Multiple Pages, to perform the switch between singlePage and standard respectively. These work fine. It seems that my printing scenario fails when I combine the actions together.

Provide the test code and the tested page URL (if applicable)

Tested page URL: https://plnkr.co/plunk/TORcbQqP9Mw4AckY (correct link)

Test code

var json = {
  pages: [
    {
      "elements": [
        {
          "type": "text",
          "name": "question1",
          "title": "First Question"
        }
      ],
      name: "page_1",
      title: "Page 1"
    },
    {
      "elements": [
        {
          "type": "text",
          "name": "question2",
          "title": "Second Question"
        }
      ],
      name: "page_2",
      title: "Page 2"
    }
  ]
};
window.survey = new Survey.Model(json);
$("#surveyElement").Survey({model: survey});

function handlePrintClicked() {
  switchToSinglePageMode();
  window.print();
  switchToStandardMode(); 
}

function switchToSinglePageMode() {
  console.log("switching to single page mode");
  survey.questionsOnPageMode = 'singlePage';
  survey.render();
}

function switchToStandardMode() {
  console.log("switching to standard mode");
  survey.questionsOnPageMode = 'standard';
  survey.render();
}

var printButton = $("#survey-print");
printButton.click(function() { handlePrintClicked() });

var singleButton = $("#survey-single");
singleButton.click(function() { switchToSinglePageMode() });

var standardButton = $("#survey-standard");
standardButton.click(function() { switchToStandardMode() });

Specify your

andrewtelnov commented 2 years ago

@schlick Unfortunately your plunker example is not related to the issue. I have created a new one, based on the code you posted. Here it is. It works as exptected. Please feel free to fork and modify it.

Thank you, Andrew

schlick commented 2 years ago

My apologies @andrewtelnov for the bad plunker link, it was definitely not what I had prepared. I've forked your plunker example and added the extra bits. Hopefully this link works: https://plnkr.co/plunk/TORcbQqP9Mw4AckY

andrewtelnov commented 2 years ago

@schlick I don't know how window.print() works. Probably it start to work when DOM is cleared but updated model is not rendered yet. Please use the following code to make it work:

function handlePrintClicked() {
  switchToSinglePageMode();
  setTimeout(() => {
    window.print();
    switchToStandardMode();
  }, 500);
}

Thank you, Andrew SurveyJS Team If you like our products, please take a moment to share your experience with our company by contributing a short review for SurveyJS page at g2.com or at Trustpilot.com. As we’re building our business, every review helps build credibility for future customers and your feedback would be greatly appreciated.

schlick commented 2 years ago

@andrewtelnov Yep, I can definitely do it that way. In fact, it works even when setting the timeout to 0. The difference I was interested it was what was the change that created this. As I said, it works with version 1.8.21. I would prefer to hook into some sort of event callback eg finished switching and rendering single page mode. It seems you can switch to single page mode (or standard mode) but it won't finish the render in the same call. This happens whether the next step is window.print() or something else. Hence that's why set timeout works. There used to be the survey.render() call that we had in our original code and which seemed to make sense (at least back at the time) eg make changes to the survey, now explicitly render it. I hope that makes sense. In any case, I can just use the timeout hack.

andrewtelnov commented 2 years ago

@schlick We are using knockoutjs inside the surveyjs juqery version. It is a tiny MVVM library. I beleive we moved to v3.5.x at that time and knockoutjs developer made a lot performance improvements. The most frameworks these days do not apply changes immediately since an observable (react) property can be changed serveral time during a short period of time. Probably this is the reason.

Thank you, Andrew

schlick commented 2 years ago

Thanks for your assistance @andrewtelnov.