surveyjs / survey-creator

Scalable open-source survey software to generate dynamic JSON-driven forms within your JavaScript application. The form builder features a drag-and-drop UI, CSS Theme Editor, and GUI for conditional logic and form branching.
https://surveyjs.io/open-source
Other
911 stars 373 forks source link

Error: Component survey is already registered #2584

Closed KuraoHikari closed 2 years ago

KuraoHikari commented 2 years ago

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

chunk-vendors.dfcfdd64.js:248 Error: Component survey is already registered, it's work properly in my local host but error in production

Captured

What is the current behavior?

What is the expected behavior?

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

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

Tested page URL:

Test code

your_code_here
<template>
  <div>
    <div id="surveyCreatorContainer"></div>
    <v-dialog
      v-model="dialog"
      width="500"
    >
      <v-card>
        <v-card-title color="error">
          {{ $t('eform.discard') }}
        </v-card-title>

        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn
            outlined
            @click="dialog = false"
          >
            No
          </v-btn>
          <v-btn
            color="primary"
            @click="discardForm"
          >
            Yes
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>

<script>
import * as SurveyCreator from 'survey-creator'
import 'survey-creator/survey-creator.css'

import * as SurveyKo from 'survey-knockout'
import * as widgets from 'surveyjs-widgets'
import { init as customWidget } from './customwidget'
import { enStrings } from './enString'

// import 'bootstrap/dist/css/bootstrap.css'
import 'survey-knockout/survey.css'

// widgets.icheck(SurveyKo);
widgets.select2(SurveyKo)
widgets.inputmask(SurveyKo)
widgets.jquerybarrating(SurveyKo)
widgets.jqueryuidatepicker(SurveyKo)
widgets.nouislider(SurveyKo)
widgets.select2tagbox(SurveyKo)
widgets.sortablejs(SurveyKo)
widgets.ckeditor(SurveyKo)
widgets.autocomplete(SurveyKo)
widgets.bootstrapslider(SurveyKo)
customWidget(SurveyKo)

SurveyCreator.StylesManager.applyTheme('default')
SurveyKo.Serializer.addProperty('question', 'tag:number')

const { CKEDITOR } = window

const CkEditor_ModalEditor = {
  afterRender(modalEditor, htmlElement) {
    if (typeof CKEDITOR === 'undefined') return
    const editor = CKEDITOR.replace(htmlElement)
    let isUpdating = false
    editor.on('change', function () {
      isUpdating = true
      modalEditor.editingValue = editor.getData()
      isUpdating = false
    })
    editor.setData(modalEditor.editingValue)
    modalEditor.onValueUpdated = function (newValue) {
      if (!isUpdating) {
        editor.setData(newValue)
      }
    }
  },
  destroy(modalEditor, htmlElement) {
    if (typeof CKEDITOR === 'undefined') return
    const instance = CKEDITOR.instances[htmlElement.id]
    if (instance) {
      instance.removeAllListeners()
      instance.destroy(true)
      CKEDITOR.remove(instance)
    }
  },
}

SurveyCreator.SurveyPropertyModalEditor.registerCustomWidget('html', CkEditor_ModalEditor)
SurveyCreator.SurveyPropertyModalEditor.registerCustomWidget('text', CkEditor_ModalEditor)

export default {
  name: 'SurveyCreator',
  props: {
    isEdit: { type: Boolean, default: false },
  },
  data() {
    return {
      data: {
        pages: [
          {
            name: 'page1',
          },
        ],
      },
      surveyCreator: null,
      dialog: false,
    }
  },
  mounted() {
    // Set the your translation to the locale
    SurveyCreator.localization.locales.en = enStrings

    // Make this locale the current
    // SurveyCreator.localization.currentLocale = "de";
    // Make french locale active
    SurveyCreator.localization.currentLocale = 'en'
    const self = this
    SurveyCreator.SurveyNestedPropertyEditorItem.dragIconName = 'icon-custom-drag'
    SurveyCreator.SurveyNestedPropertyEditorItem.deleteIconName = 'icon-custom-delete'
    SurveyKo.settings.allowShowEmptyTitleInDesignMode = false

    // Color customization
    const mainColor = '#0078d4'
    const mainHoverColor = '#60C5FB'
    const textColor = '#4a4a4a'
    const headerColor = '#000000'
    const headerBackgroundColor = '#ffffff'
    const bodyContainerBackgroundColor = '#f8f8f8'
    const defaultThemeColorsSurvey = SurveyKo.StylesManager.ThemeColors.default
    defaultThemeColorsSurvey['$main-color'] = mainColor
    defaultThemeColorsSurvey['$main-hover-color'] = mainHoverColor
    defaultThemeColorsSurvey['$text-color'] = textColor
    defaultThemeColorsSurvey['$header-color'] = headerColor
    defaultThemeColorsSurvey['$header-background-color'] = headerBackgroundColor
    defaultThemeColorsSurvey['$body-container-background-color'] = bodyContainerBackgroundColor
    const defaultThemeColorsEditor = SurveyCreator.StylesManager.ThemeColors.default
    defaultThemeColorsEditor['$primary-color'] = mainColor
    defaultThemeColorsEditor['$secondary-color'] = mainColor
    defaultThemeColorsEditor['$primary-hover-color'] = mainHoverColor
    defaultThemeColorsEditor['$primary-text-color'] = textColor
    defaultThemeColorsEditor['$selection-border-color'] = mainColor
    SurveyKo.StylesManager.applyTheme()
    SurveyCreator.StylesManager.applyTheme()

    // Hide some properties of the itemvalue object
    // Design itemvalue[] property editor
    SurveyKo.Serializer.findProperty('itemvalue', 'visibleIf').visible = false
    SurveyKo.Serializer.findProperty('itemvalue', 'enableIf').visible = false
    SurveyKo.Serializer.findProperty('itemvalue', 'text').visible = false

    // Make the detail editor for itemvalue invisible, hide Edit button
    // SurveyCreator.SurveyQuestionEditorDefinition.definition['itemvalue[]@choices'].tabs = [
    //   { name: 'general', visible: false },
    // ]

    // const options = {
    //   // show the embedded survey tab. It is hidden by default
    //   showEmbeddedSurveyTab: false,

    //   // hide the test survey tab. It is shown by default
    //   showTestSurveyTab: true,

    //   // hide the JSON text editor tab. It is shown by default
    //   showJSONEditorTab: true,

    //   // show the "Options" button menu. It is hidden by default
    //   showOptions: false,
    // }

    const options = {
      showEmbeddedSurveyTab: false,
      showTestSurveyTab: true,
      showOptions: false,
      showLogicTab: false,
      showJSONEditorTab: false,
      questionTypes: [
        'text',
        'checkbox',
        'radiogroup',
        'dropdown',
        'comment',
        'rating',
        'imagepicker',
        'boolean',
        'html',

        // 'file',
        'expression',
      ],

      // pageEditMode: 'single',
      showTitlesInExpressions: true,
      allowEditExpressionsInTextEditor: false,
      showSurveyTitle: 'always',
    }

    this.surveyCreator = new SurveyCreator.SurveyCreator('surveyCreatorContainer', options)

    // Add custom button in the toolbar
    this.surveyCreator.toolbarItems.push({
      id: 'discard-survey',
      visible: true,
      title: 'Discard Form',
      action() {
        self.dialog = true
      },
    })

    // console.log(this.isEdit, 'aaaaaaaaaaaaaaaaaaaaaaaaaa')
    // console.log(this.isEdit, 'aaaaaaaaaaaaaaaaaaaaaaaaaaCCCCCCCCCCCCC')
    if (this.isEdit === true) {
      const dataForm = this.$store.getters['link/getSaveDataEform']

      this.surveyCreator.text = JSON.stringify(dataForm.survey)
    } else {
      this.surveyCreator.text = JSON.stringify(this.data)
    }

    // this.surveyCreator.text = JSON.stringify(this.data)

    this.surveyCreator.saveSurveyFunc = function () {
      self.$emit('save-survey', JSON.parse(this.text))
    }

    // Show toolbox in the right container. It is shown on the left by default
    this.surveyCreator.showToolbox = 'right'

    // Show property grid in the right container, combined with toolbox
    this.surveyCreator.showPropertyGrid = 'right'

    // Make toolbox active by default
    this.surveyCreator.rightContainerActiveItem('toolbox')

    // Remove default properties layout in property grid and have only one "general" category.
    SurveyCreator.SurveyQuestionEditorDefinition.definition = {}

    // Define visibleIndex for properties we want to show and set attribute that marks we want to show this property
    let maxVisibleIndex = 0
    function showTheProperty(className, propertyName, visibleIndex) {
      if (!visibleIndex) visibleIndex = ++maxVisibleIndex
      else if (visibleIndex > maxVisibleIndex) maxVisibleIndex = visibleIndex

      // Use Survey Serializer to find the property, it looks for property in the class and all it's parents
      const property = SurveyKo.Serializer.findProperty(className, propertyName)
      if (!property) return
      property.visibleIndex = visibleIndex

      // Custom JavaScript attribute that we will use in onShowingProperty event
      property.showProperty = true
    }
    showTheProperty('question', 'name')
    showTheProperty('question', 'title')
    showTheProperty('question', 'description')
    showTheProperty('question', 'visible')
    showTheProperty('question', 'required')
    showTheProperty('checkbox', 'choices')
    showTheProperty('checkbox', 'hasOther')
    showTheProperty('checkbox', 'hasSelectAll')
    showTheProperty('checkbox', 'hasNone')
    showTheProperty('text', 'inputType')
    showTheProperty('text', 'placeHolder')
    showTheProperty('comment', 'placeHolder')
    showTheProperty('comment', 'rows')

    // Use it to show properties that has our showProperty custom attribute equals to true
    this.surveyCreator.onShowingProperty.add(function (sender, options) {
      options.canShow = options.property.showProperty === true
    })

    // Remove toolbar items except undo/redo buttons
    this.surveyCreator.toolbarItems.splice(3, 1)

    // Set custom designer placeholder
    this.surveyCreator.placeholderHtml =
      '<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center;">' +
      '<img src="https://surveyjs.io/Content/Images/examples/drag-image.svg" />' +
      '<div style="font-size: 16px; max-width: 210px;">' +
      'Drag and drop a question to start designing your form' +
      '</div>' +
      '</div>'

    // Adorners for item inplace editing edit itemvalue.value and not itemvalue.text
    this.surveyCreator.inplaceEditForValues = true

    // Hide Fast Entry option for ItemValue[] editor
    this.surveyCreator.onSetPropertyEditorOptions.add(function (sender, options) {
      options.editorOptions.showTextView = false
    })

    // Add title for the sidebar panel
    const rightContainerElement = document.getElementsByClassName('svd-designer-container--right-side')[0]
    const titleDiv = document.createElement('div')
    titleDiv.className = 'svd-sidebar-title'
    titleDiv.innerText = 'Questions'
    titleDiv.style = 'font-size: 16px;'
    rightContainerElement.insertBefore(titleDiv, rightContainerElement.children[1])
  },
  methods: {
    discardForm() {
      this.$router.push({ name: 'e-form' }, () => {})
    },
  },
}
</script>

create.js

<template>
  <div>
    <!-- <pre>{{phoneNumber}}</pre> -->
    <alert-dialog
      :dialog="alertDialog"
      :title="alertTitle"
      :text="alertText"
      @close="alertDialog = false"
    />
    <v-card>
      <v-card-text>
        <v-row>
               <v-col
            cols="12"
            md="6"
          >
            <v-select
                    v-model="phoneNumber"
                    :items="instances"
                    item-text="label"
                    item-value="value"
                    outlined
                    :label="$t('channels.channel')"
                    hide-details

                    required
                    class="mb-3"

                    attach
                  ></v-select>
          </v-col>
          <v-col
            cols="12"
            md="6"
          >

            <v-text-field
              v-model="eFormTitle"
              :label="$t('eform.title')"
              outlined
            ></v-text-field>
          </v-col>

        </v-row>
        <v-row>
          <v-col
            cols="12"
            md="6"
          >
            <v-text-field
              v-model="eFormFacebookPixel"
              required
              label="Pixel ID"
              :prepend-inner-icon="icons.mdiCounter"
              outlined
              hide-details
              class="mb-3"
              type="number"
              placeholder="1236776XXX"
            ></v-text-field>
          </v-col>
          <v-col
            cols="12"
            md="6"
          >
            <v-text-field
              v-model="eFormDescription"
              :label="$t('eform.description')"
              outlined
            ></v-text-field>
          </v-col>
          <v-col
            cols="12"
            md="6"
          >
            <v-text-field
              v-model="eFormGoogleTagManager"
              required
              label="Tag Manager ID"
              :prepend-inner-icon="icons.mdiPoundBoxOutline"
              outlined
              placeholder="GTM-123XXX"
              class="mb-3"
              :hint="$t('LinkGenerator.tutorialSlugFour')"
              persistent-hint
            ></v-text-field>
          </v-col>
        </v-row>
        <!-- <v-row>
          <v-col cols="6" md="3">
            <v-select
              v-model="contactListSelected"
              :items="dataListContact2"
              item-text="list_name"
              outlined
              return-object
              :label="`Contact`"
              disabled
              hide-details
              required
              class="mb-5"
            ></v-select>
          </v-col>
          <v-col
            cols="6"
            md="3"
          >
            <v-btn
              color="primary"
              class=""
              @click="openNewList"
            >
              <span>Add Contact List</span>
              <v-icon>
                {{ icons.mdiPlusCircle }}
              </v-icon>
            </v-btn>
          </v-col>
        </v-row> -->
        <v-divider></v-divider>
        <v-row>
          <v-col cols="12">
            <survey-creator
              :is-edit="edit"
              @save-survey="saveSurvey"
            ></survey-creator>
          </v-col>
        </v-row>
      </v-card-text>
      <dialogAddListContact ref="dialogAddListContact"></dialogAddListContact>
    </v-card>
  </div>
</template>
<script>
import {
  mdiFormSelect,
  mdiInformationOutline,
  mdiPlus,
  mdiRadioTower,
  mdiCounter,
  mdiImageFilterCenterFocusWeak,
  mdiPoundBoxOutline,
  mdiPlusCircle,
} from '@mdi/js'
import PouchDB from 'pouchdb-browser'
import eFormMixin from '@/mixins/eFormMixin'
import pouchDbMixin from '../../mixins/pouchDbMixin'
import contactMixin from '../../mixins/contactMixin'
import dialogAddListContact from '../component/DialogAddListContact.vue'
import SurveyCreator from '@/components/surveyjs/SurveyCreator.vue'
import AlertDialog from '@/components/dialog/AlertDialog.vue'

PouchDB.adapter('worker', require('worker-pouch'))

export default {
  name: 'EFormCreate',

  components: {
    SurveyCreator,
    AlertDialog,
    dialogAddListContact,
  },

  mixins: [eFormMixin, pouchDbMixin, contactMixin],
  props: ['edit'],

  setup() {
    return {
      icons: {
        mdiFormSelect,
        mdiInformationOutline,
        mdiPlus,
        mdiRadioTower,
        mdiCounter,
        mdiImageFilterCenterFocusWeak,
        mdiPoundBoxOutline,
        mdiPlusCircle,
      },
    }
  },

Specify your

tsv2013 commented 2 years ago

Moved to the corresponding repo

tsv2013 commented 2 years ago

It looks like you're loading survey-knockout scripts (used by SurveyJS Creator V1) twice. I believe you know about the https://github.com/surveyjs/surveyjs_vue_quickstart boilerplate repo - it works ok for me.

In order to fix the issue we need to reproduce it locally. Could you share a link to the minimal reproducible example as described e.g. here - https://stackoverflow.com/help/minimal-reproducible-example and we'll check it

KuraoHikari commented 2 years ago

thanks, it seems like the webpack is kinda corrupted, now it's fixed by just rebuilding the project and re deployed again