surveyjs / custom-widgets

The collection of custom widgets for SurveyJS: Survey Library and Survey Creator :package:
https://surveyjs.io
MIT License
79 stars 78 forks source link

Add custom widget ERROR TypeError: Cannot read property 'getType' of null #146

Open npupiec opened 5 years ago

npupiec commented 5 years ago

Hi

when I try to add a new widget I get this error in the console ERROR TypeError: Cannot read property 'getType' of null. The project is in Angular 7. Versions: "survey-angular": "1.1.4", "survey-creator": "1.1.4", "survey-knockout": "1.1.4", "survey-pdf": "1.1.4", "surveyjs-widgets": "1.1.4",

My code: export var sort = { name: "sort", title: "Sort", iconName: "", widgetIsLoaded: function () { return true; }, isFit: function (question) { return question.getType() === 'sort'; }, activatedByChanged: function (activatedBy) { Survey.JsonObject.metaData.addClass("sort", [ { name: "width", visible: false }, { name: "useDisplayValuesInTitle", visible: false }, { name: "useDisplayValuesInTitle", visible: false }, ], null, "empty");

  Survey.JsonObject.metaData.addProperty("sort", {
    name: "sortables:itemvalues",
    default: [{
      value: "https://responsivedesign.is/wp-content/uploads/2014/10/be-inspired.svg",
      text: "item1"
    },
      {
        value: "https://crossweb.pl/upload/gallery/cycles/621/300x300/nlg2ymvo-lw2ht_a1r_ak4ka2wimesyqnq.png",
        text: "item2"
      },
      {
        value: "https://hackone.co/wp-content/uploads/2018/06/Logo-example-2-01-3.svg",
        text: "item3"
      }
    ],
  });

  Survey.JsonObject.metaData.addProperty("sort", {
    name: "answerType",
    choices: ["text", "images"],
    default: "text"
  });

  Survey.JsonObject.metaData.addProperty("sort", {
    name: "mode",
    choices: ["click&drag", "click"],
    default: "click"
  });

  Survey.JsonObject.metaData.addProperty("sort", {
    name: "showImageSubtitles:boolean",
    default: true
  });
},
isDefaultRender: false,
htmlTemplate: '<div></div>',
afterRender: function (question, el) {
  //--------------CONST AND FUNC DEFINITIONS--------------------//
  const shouldSort = question.mode != "click" ? true : false;
  let clickedSortTempAnswer = [];

  const initializeUserAnswers = function (answers) {
    const userAnswersElementWrapper = document.createElement("div");
    el.appendChild(userAnswersElementWrapper);
    const userAnswersElement = document.createElement("div");
    userAnswersElementWrapper.classList.add("user-answers-wrapper");
    userAnswersElement.classList.add("user-answers")
    if (question.answerType === "images") {
      userAnswersElement.classList.add("flex");
    }

    for (answer of answers) {
      for (sortable of question.sortables) {
        if (answer === sortable.text) {
          let answerElement = document.createElement('div');
          answerElement.dataset.question = question.name;
          answerElement.dataset.answer = answer;
          answerElement.classList.add("answer");

          if (question.answerType === 'text') {
            answerElement.innerText = sortable.text;
          } else if (question.answerType === 'images') {
            let imageElement = document.createElement('img');
            answerElement.appendChild(imageElement);
            imageElement.src = sortable.value;
            imageElement.classList.add("image-answer");

            if (question.showImageSubtitles) {
              let titleElement = document.createElement('span');
              titleElement.classList.add("answer-title");
              titleElement.innerText = sortable.text;
              answerElement.appendChild(titleElement);
            }
          }
          if (question.mode === "click") {
            answerElement.onclick = handleClickSort;

            if (typeof question.defaultValue !== 'undefined' && question.defaultValue.includes(sortable.text)) {
              const numberElement = document.createElement('p');
              answerElement.classList.add("disabled");
              numberElement.classList.add("answer-number");
              const index = question.defaultValue.indexOf(sortable.text);
              numberElement.innerText = index + 1;
              answerElement.appendChild(numberElement);
            }
          }
          userAnswersElement.appendChild(answerElement);
        }
      }
    }

    userAnswersElementWrapper.appendChild(userAnswersElement);
    el.appendChild(userAnswersElementWrapper);

    new Sortable(userAnswersElement, {
      group: {
        name: 'answers' + question.name,
        pull: false,
        put: false,
      },
      animation: 150,
      sort: shouldSort,
      onEnd: function () {
        const tempAnswer = [];
        for (answer of userAnswersElement.childNodes) {
          tempAnswer.push(answer.dataset.answer);
        }
        question.value = tempAnswer;
      }
    });
  }

  const handleClickSort = function (event) {
    const clickedElement = event.srcElement;
    clickedSortTempAnswer.push(clickedElement.dataset.answer);
    clickedElement.classList.add("disabled");
    question.value = clickedSortTempAnswer;

    const numberElement = document.createElement('p');
    numberElement.classList.add("answer-number")
    numberElement.innerText = clickedSortTempAnswer.length;
    clickedElement.appendChild(numberElement);
  }

  const handleReset = function () {
    const elements = el.getElementsByTagName('div');
    clickedSortTempAnswer = [];
    question.value = question.mode !== "click" ? sortablesTextsList : undefined;
    for (element of elements) {
      if (element.dataset.question === question.name) {
        const numberElements = element.getElementsByTagName('p');
        if (numberElements.length != 0) {
          numberElements[0].remove();
          element.classList.remove("disabled");
        }
      }
    }
  }

  //----------INIT-------------

  const sortablesTextsList = question.sortables.map(sortable => sortable.text);
  let answersToInitialize = []

  answersToInitialize = question.mode === "click" || (question.mode === "click&drag" && typeof question.defaultValue === 'undefined') ?
      sortablesTextsList : question.defaultValue;

  initializeUserAnswers(answersToInitialize);

  if (question.mode === 'click') {
    const resetButton = document.createElement('button');
    resetButton.innerText = "Reset";
    resetButton.onclick = handleReset;
    resetButton.classList.add("reset-button");
    el.appendChild(resetButton);
  }
},
willUnmount: function (question, el) {}

} and I add to my component SurveyKo.CustomWidgetCollection.Instance.addCustomWidget(widget.sort, 'customtype');

tsv2013 commented 5 years ago

Could you provide us with a plunker (or other sandbox) minimal working sample? You can take this one https://plnkr.co/edit/HdnYE5?p=preview as a staring point