Skip to content

Commit

Permalink
Vue3: Fix onAfterRenderQuestion and onAfterRenderQuestionInput are fi…
Browse files Browse the repository at this point in the history
…red with null html element (#7216)

* Work for #7173: fix ref is not passed for some questions in Vue 3

* Work for #7173: fix onAfterRenderQuestion is not fired when quesiton is lazy rendered
  • Loading branch information
dk981234 authored Oct 24, 2023
1 parent 93d2dfa commit c41787e
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 11 deletions.
1 change: 1 addition & 0 deletions packages/survey-vue3-ui/src/BooleanSwitch.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<div
:class="question.cssClasses.root"
ref="root"
v-on:keydown="question.onKeyDownCore($event)"
>
<label :class="question.getItemCss()">
Expand Down
4 changes: 3 additions & 1 deletion packages/survey-vue3-ui/src/Checkbox.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<template>
<fieldset :class="question.getSelectBaseRootCss()"
<fieldset
:class="question.getSelectBaseRootCss()"
ref="root"
:role="question.a11y_input_ariaRole"
:aria-required="question.a11y_input_ariaRequired"
:aria-label="question.a11y_input_ariaLabel"
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-vue3-ui/src/DropdownSelect.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div :class="question.renderCssRoot">
<div :class="question.renderCssRoot" ref="root">
<div :class="question.cssClasses.selectWrapper">
<select
v-if="!question.isReadOnly"
Expand Down
15 changes: 12 additions & 3 deletions packages/survey-vue3-ui/src/Element.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import type {
PanelModel,
} from "survey-core";
import { useBase } from "./base";
import { computed, onMounted, ref } from "vue";
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
const props = defineProps<{
survey: SurveyModel;
Expand Down Expand Up @@ -119,9 +119,18 @@ const getContentClass = (element: Question) => {
useBase(() => props.element);
onMounted(() => {
if (!props.element.isPanel) {
const afterRender = () => {
if (!props.element.isPanel && root.value) {
(props.element as Question).afterRender(root.value as HTMLElement);
}
};
const stopWatch = watch(
() => root.value,
() => {
afterRender();
}
);
onUnmounted(() => {
stopWatch();
});
</script>
2 changes: 1 addition & 1 deletion packages/survey-vue3-ui/src/File.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div :class="question.fileRootCss">
<div :class="question.fileRootCss" ref="root">
<input
:class="question.cssClasses.fileInput"
v-if="!question.isReadOnly && question.hasFileUI"
Expand Down
22 changes: 17 additions & 5 deletions src/vue/element.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<div :class="!element.isPanel ? element.getRootCss() : null"
v-if="row.isNeedRender"
ref="root"
v-on:focusin="element.focusIn()"
:id="element.id"
:role="element.ariaRole"
Expand Down Expand Up @@ -66,6 +67,7 @@

<component
v-else-if="!!element.skeletonComponentName"
ref="root"
:is="element.skeletonComponentName"
:element="element"
:css="css"
Expand All @@ -74,7 +76,7 @@

<script lang="ts">
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { Component, Prop, Watch } from "vue-property-decorator";
import { Base, SurveyModel, Question, QuestionRowModel } from "survey-core";
import { getComponentName } from "./question";
import { BaseVue } from "./base";
Expand All @@ -100,12 +102,22 @@ export class SurveyElementVue extends BaseVue {
get hasErrorsOnBottom() {
return !this.element.isPanel && (<Question>this.element).showErrorOnBottom;
}
mounted() {
if (!this.element.isPanel) {
(<Question>this.element).afterRender(this.$el as HTMLElement);
previousElement: HTMLElement;
afterRender(el: HTMLElement) {
if (!this.element.isPanel && this.previousElement !== el && el && el instanceof HTMLElement) {
(<Question>this.element).afterRender(el);
}
this.previousElement = el;
}
onUpdated() {
this.afterRender(this.$refs.root as HTMLElement);
}
mounted(): void {
this.afterRender(this.$refs.root as HTMLElement)
}
destroyed(): void {
this.previousElement = undefined as any;
}
}
Vue.component("survey-element", SurveyElementVue);
export default SurveyElementVue;
Expand Down
56 changes: 56 additions & 0 deletions testCafe/survey/afterRenderEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { ClientFunction, Selector } from "testcafe";
import { frameworks, url_test, initSurvey } from "../helper";

const title = "afterRenderQuestionEvent";

const json = {
pages: [
{
name: "page1",
title: "page one",
elements: [
{
type: "radiogroup",
name: "q1",
choices: ["1", "2", "3"],
},
{
type: "text",
visibleIf: "{q1} = '1'",
name: "q2",
isRequired: true,
},
{
type: "text",
name: "q3",
},
{
type: "text",
name: "q4",
}
],
},
],
};

frameworks.forEach((framework) => {
fixture`${framework} ${title}`.page`${url_test}defaultV2/${framework}`.beforeEach(async (t) => {
await t.resizeWindow(1920, 1080);
});
test("afterRender is not fired when questions are lazy rendered", async (t) => {
await ClientFunction(() => {
(window as any).Survey.settings.lazyRowsRendering = true;
})();
const f = (survey, options) => {
options.htmlElement.setAttribute("test", true);
};
const events = { onAfterRenderQuestion: f };
await initSurvey(framework, json, events);

await t.click(Selector("label").nth(0))
.expect(Selector("div[data-name='q1']").hasAttribute("test")).ok()
.expect(Selector("div[data-name='q2']").hasAttribute("test")).ok()
.expect(Selector("div[data-name='q3']").hasAttribute("test")).ok()
.expect(Selector("div[data-name='q4']").hasAttribute("test")).ok();
});
});

0 comments on commit c41787e

Please sign in to comment.