Skip to content

Commit

Permalink
Work for #2756 - Support Vue 3 in SurveyJS library - Added other simp…
Browse files Browse the repository at this point in the history
…le questions
  • Loading branch information
tsv2013 committed Dec 29, 2022
1 parent ef28fcf commit b75a41c
Show file tree
Hide file tree
Showing 11 changed files with 637 additions and 0 deletions.
56 changes: 56 additions & 0 deletions packages/survey-vue-ui/src/Comment.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<textarea
v-if="!question.isReadOnlyRenderDiv()"
:readonly="question.isInputReadOnly"
:disabled="question.renderedInputDisabled"
:value="question.value"
:id="question.inputId"
:maxlength="question.getMaxLength()"
:cols="question.cols"
:rows="question.rows"
:placeholder="question.renderedPlaceholder"
:class="question.className"
@change="change"
@input="(e) => { question.onInput(e) }"
@keydown="(e) => { question.onKeyDown(e) }"
:aria-required="question.ariaRequired"
:aria-label="question.ariaLabel"
:aria-invalid="question.ariaInvalid"
:aria-describedby="question.ariaDescribedBy"
v-bind:style="{ resize: question.resizeStyle }"
></textarea>
<div v-else>{{ question.value }}</div>
</template>

<script lang="ts">
import { QuestionCommentModel } from "survey-core";
import { defineSurveyComponent } from "./base";
export default defineSurveyComponent({
// eslint-disable-next-line
name: "survey-comment",
props: {
question: QuestionCommentModel,
css: Object,
},
data: (vm: any) => {
return {
getModel: () => { return vm.question; },
change(event: any) {
vm.question.value = event.target.value;
}
}
},
mounted() {
if (this.question) {
this.question.afterRenderQuestionElement(this.$el as HTMLElement);
}
},
unmounted() {
if (this.question) {
this.question.beforeDestroyQuestionElement(this.$el as HTMLElement);
}
}
});
</script>
58 changes: 58 additions & 0 deletions packages/survey-vue-ui/src/Errors.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<template>
<div
role="alert"
aria-live="polite"
v-if="element.hasVisibleErrors"
:class="element.cssError"
:id="element.id + '_errors'"
>
<div v-for="(error, index) in element.errors" :key="'error_' + index">
<span
:class="element.cssClasses ? element.cssClasses.error.icon || undefined : 'panel-error-icon'"
aria-hidden="true"
></span>
<span
:class="element.cssClasses ? element.cssClasses.error.item || undefined: 'panel-error-item'"
>
<survey-string :locString="error.locText" />
</span>
</div>
</div>
</template>

<script lang="ts">
import { SurveyElement, TooltipManager, Base, Question, PanelModel } from "survey-core";
import { defineSurveyComponent } from "./base";
export default defineSurveyComponent({
// eslint-disable-next-line
name: "survey-errors",
props: {
element: Object,
location: String,
},
data: (vm: any) => {
return {
tooltipManager: undefined,
getModel: () => { return vm.element; }
}
},
updated() {
if (this.location == "tooltip" && this.$el instanceof HTMLElement) {
if (!this.tooltipManager || this.$el !== this.tooltipManager.tooltipElement) {
this.tooltipManager = new TooltipManager(<HTMLElement>this.$el);
}
}
if (!(this.$el instanceof HTMLElement) && !!this.tooltipManager) {
this.tooltipManager.dispose();
}
},
unmounted() {
if (!!this.tooltipManager) {
this.tooltipManager.dispose();
}
}
});
</script>
33 changes: 33 additions & 0 deletions packages/survey-vue-ui/src/Expression.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<div :class="question.cssClasses.text">{{ question.formatedValue }}</div>
</template>

<script lang="ts">
import { QuestionExpressionModel } from "survey-core";
import { defineSurveyComponent } from "./base";
export default defineSurveyComponent({
// eslint-disable-next-line
name: "survey-expression",
props: {
question: QuestionExpressionModel,
css: Object,
},
data: (vm: any) => {
return {
getModel: () => { return vm.question; }
}
},
mounted() {
if (this.question) {
this.question.afterRenderQuestionElement(this.$el as HTMLElement);
}
},
unmounted() {
if (this.question) {
this.question.beforeDestroyQuestionElement(this.$el as HTMLElement);
}
}
});
</script>
158 changes: 158 additions & 0 deletions packages/survey-vue-ui/src/File.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<template>
<div :class="question.fileRootCss">
<input
:class="question.cssClasses.fileInput"
v-if="!question.isReadOnly"
tabindex="-1"
type="file"
:id="question.inputId"
@change="question.doChange"
:aria-required="question.ariaRequired"
:aria-label="question.ariaLabel"
:aria-invalid="question.ariaInvalid"
:aria-describedby="question.ariaDescribedBy"
:multiple="question.multipleRendered"
v-bind:title="question.inputTitle"
v-bind:accept="question.acceptedTypes"
/>
<input
v-if="question.isReadOnly"
type="file"
disabled
:id="question.inputId"
:class="question.getReadOnlyFileCss()"
:multiple="question.multipleRendered"
:placeholder="question.title"
style="color: transparent"
/>
<div
:class="question.cssClasses.dragArea"
@drop="question.onDrop"
@dragover="question.onDragOver"
@dragleave="question.onDragLeave"
@dragenter="question.onDragEnter"
>
<div
:class="question.getFileDecoratorCss()"
>
<span :class="question.cssClasses.dragAreaPlaceholder">{{ question.dragAreaPlaceholder }}</span>
<div :class="question.cssClasses.wrapper">
<label
role="button"
tabindex="0"
:class="question.getChooseFileCss()"
:for="question.inputId"
v-bind:aria-label="question.chooseButtonCaption"
>
<span>{{ question.chooseButtonCaption }}</span>
<sv-svg-icon v-if="question.cssClasses.chooseFileIconId" :title="question.chooseButtonCaption" :iconName="question.cssClasses.chooseFileIconId" :size="'auto'"></sv-svg-icon>
</label>
<span
:class="question.cssClasses.noFileChosen"
v-if="question.isEmpty()"
>{{ question.noFileChosenCaption }}</span
>
</div>
</div>
<button
type="button"
v-if="question.showRemoveButton"
:class="question.cssClasses.removeButton"
@click="question.doClean"
>
<span>{{ question.clearButtonCaption }}</span>
<sv-svg-icon v-if="question.cssClasses.removeButtonIconId" :iconName="question.cssClasses.removeButtonIconId" :size="'auto'" :title="question.clearButtonCaption"></sv-svg-icon>
</button>
<div :class="question.cssClasses.fileList || undefined" v-if="!question.isEmpty()">
<span
v-for="(val, index) in question.previewValue"
:key="question.inputId + '_' + index"
v-show="val && question.isPreviewVisible(index)"
:class="question.cssClasses.preview"
>
<div v-if="val.name && question.cssClasses.fileSign" :class="question.cssClasses.fileSign">
<a
@click="question.doDownloadFile($event, val)"
:href="val.content"
:title="val.name"
:download="val.name"
:style="{width: question.imageWidth}"
>{{ val.name }}</a
>
</div>
<div :class="question.cssClasses.imageWrapper">
<img
v-if="question.canPreviewImage(val)"
:src="val.content"
:style="{height: question.imageHeight, width: question.imageWidth}"
alt="File preview"
/>
<sv-svg-icon v-if="question.defaultImage(val)"
:iconName="question.cssClasses.defaultImageIconId" :class="question.cssClasses.defaultImage" :size="'auto'"></sv-svg-icon>
<div v-if="val.name && !question.isReadOnly" :class="question.cssClasses.removeFileButton" @click="question.doRemoveFile(val)">
<span
:class="question.cssClasses.removeFile"
>{{ question.removeFileCaption }}</span
>
<sv-svg-icon v-if="question.cssClasses.removeFileSvgIconId" :title="question.removeFileCaption" :class="question.cssClasses.removeFileSvg" :iconName="question.cssClasses.removeFileSvgIconId" :size="'auto'"></sv-svg-icon>
</div>
</div>
<div v-if="val.name && question.cssClasses.fileSignBottom" :class="question.cssClasses.fileSignBottom">
<a
@click="question.doDownloadFile($event, val)"
:href="val.content"
:title="val.name"
:download="val.name"
:style="{width: question.imageWidth}"
>{{ val.name }}</a
>
</div>
</span>
</div>
<button
type="button"
v-if="question.showRemoveButtonBottom"
:class="question.showRemoveButtonBottom"
@click="question.doClean"
>
<span>{{ question.clearButtonCaption }}</span>
<sv-svg-icon v-if="question.cssClasses.removeButtonIconId" :iconName="question.cssClasses.removeButtonIconId" :size="'auto'" :title="question.clearButtonCaption"></sv-svg-icon>
</button>
<sv-action-bar v-if="question.mobileFileNavigatorVisible" :model="question.mobileFileNavigator"></sv-action-bar>
</div>
</div>
</template>

<script lang="ts">
import { QuestionFileModel } from "survey-core";
import { confirmAction, detectIEOrEdge, loadFileFromBase64 } from "survey-core";
import { defineSurveyComponent } from "./base";
export default defineSurveyComponent({
// eslint-disable-next-line
name: "survey-file",
props: {
question: QuestionFileModel,
css: Object,
},
data: (vm: any) => {
return {
getModel: () => { return vm.question; },
doRemoveFile(data: any) {
this.question.doRemoveFile(data);
}
}
},
mounted() {
if (this.question) {
this.question.afterRenderQuestionElement(this.$el as HTMLElement);
}
},
unmounted() {
if (this.question) {
this.question.beforeDestroyQuestionElement(this.$el as HTMLElement);
}
}
});
</script>
26 changes: 26 additions & 0 deletions packages/survey-vue-ui/src/Html.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<div
:class="question.renderCssRoot"
v-html="question.locHtml.renderedHtml"
></div>
</template>

<script lang="ts">
import { QuestionHtmlModel } from "survey-core";
import { ref, defineComponent, type ComponentOptions, unref } from "vue";
export default defineComponent({
// eslint-disable-next-line
name: "survey-html",
props: {
question: QuestionHtmlModel,
css: Object,
},
data: (vm: any) => {
return {
getModel: () => { return vm.question; },
}
}
});
</script>
49 changes: 49 additions & 0 deletions packages/survey-vue-ui/src/Image.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<template>
<div :class="question.cssClasses.root">
<img
v-if="question.renderedMode === 'image'"
:class="question.getImageCss()"
:src="question.locImageLink.renderedHtml"
:alt="question.altText || question.title"
:width="question.renderedWidth"
:height="question.renderedHeight"
v-bind:style="{ objectFit: question.imageFit }"
/><video
controls
v-if="question.renderedMode === 'video'"
:class="question.getImageCss()"
:src="question.locImageLink.renderedHtml"
:width="question.renderedWidth"
:height="question.renderedHeight"
v-bind:style="{ objectFit: question.imageFit }"
></video>
<iframe
v-if="question.renderedMode === 'youtube'"
:class="question.getImageCss()"
:src="question.locImageLink.renderedHtml"
:width="question.renderedWidth"
:height="question.renderedHeight"
v-bind:style="{ objectFit: question.imageFit }"
></iframe>
</div>
</template>

<script lang="ts">
import { QuestionImageModel } from "survey-core";
import { ref, defineComponent, type ComponentOptions, unref } from "vue";
export default defineComponent({
// eslint-disable-next-line
name: "survey-image",
props: {
question: QuestionImageModel,
css: Object,
},
data: (vm: any) => {
return {
getModel: () => { return vm.question; },
}
}
});
</script>
Loading

0 comments on commit b75a41c

Please sign in to comment.