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.11k stars 801 forks source link

Table Of Contents - Display a special mark within a page item when a page contains errors #7320

Closed JaneSjs closed 1 week ago

JaneSjs commented 10 months ago

User issue: T15426 - enable required panels/pages to ignore custom questions when validating https://surveyjs.answerdesk.io/internal/ticket/details/T15426


Add an option to display some special mark within a page's title to inform users that a page contains errors. image

JaneSjs commented 10 months ago

It is possible to display a special sign for a Table Of Contents page item using the Markdown feature.

View CodeSandbox.

Here are main implementation steps.

Serializer.addProperty("page", { name: "errorMarkExists", type: "boolean", default: false });

* Implement the [survey.onTextMarkdown](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onTextMarkdown) function to add a special character (`#`) to a page's navigtion title if a page contains errors.
```js
survey.onTextMarkdown.add((sender, options) => {
    const el = options.element;
    console.log(
      "name: " +
        options.name +
        ", text: " +
        options.text +
        ", element type: " +
        el.getType()
    );
    if (!el || el.getType() !== "page") return;

    if (options.name === "navigationTitle") {
      const page = el;
      const pi = page.getProgressInfo();
      const isCompleted = pi.questionCount === pi.answeredQuestionCount;
      let hasErrors = false;
      const questions = page.questions;
      for (let i = 0; i < questions.length; i++) {
        if (questions[i].errors.length > 0) {
          hasErrors = true;
          break;
        }
      }
      let html = "";
      if (hasErrors && !el.errorMarkExists) {
        el.errorMarkExists = true;
      } else if (!hasErrors && el.errorMarkExists) {
        el.errorMarkExists = false;
      }

      if (el.errorMarkExists) {
        if (options.text.indexOf("#") < 0) {
          html = options.text + "#";
        } else {
          html = options.text;
        }
      } else {
        html = options.text.replace("#", "");
      }

      if (!isCompleted) {
        html = "<strong>" + html + "</strong>";
      }
      options.html = html;
    }
});

Now, when a user attempts to complete a survey which contains errors, an error indicator appears within Table Of Contents. image

JaneSjs commented 1 week ago

With v1.11.14, it is possible to override an item component template for a Table of Contents.

The following demo shows how to implement a custom TOC item and:

Follow these steps:

  1. Implement a component that renders item markup. The component accepts the item configuration object as a prop. You can use its item property to access the IAction which corresponds to the current page item within a TOC. Use this object to retrieve information about the current page and its answered and total question count.

  2. Register the component so that it can be accessed by name.

In React and other JS applications, register the component in ReactElementFactory as shown in the CustomTocItem.jsx file. In Angular, register the component in AngularComponentFactory as shown in the toc-custom-item.component.ts file. In Vue, implement the CustomTocItem component as shown in the CustomTocItem.vue file and register it within application components.

  1. Obtain the Table of Contents navigation element and set the itemComponent property to the custom component name.
    survey.findLayoutElement("toc-navigation").data.listModel.itemComponent = "sv-custom-toc-item";