Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ranking animations #8314

Merged
merged 11 commits into from
May 29, 2024
5 changes: 5 additions & 0 deletions packages/survey-angular-ui/src/base-angular.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export abstract class BaseAngular<T extends Base = Base> extends EmbeddedViewCon
this.update(key);
}
};
stateElement.enableOnElementRenderedEvent();
}
}
private unMakeBaseElementAngular(stateElement?: Base) {
Expand All @@ -82,6 +83,7 @@ export abstract class BaseAngular<T extends Base = Base> extends EmbeddedViewCon
val["onArrayChanged"] = () => { };
}
});
stateElement.disableOnElementRenderedEvent();
}
}

Expand Down Expand Up @@ -109,6 +111,9 @@ export abstract class BaseAngular<T extends Base = Base> extends EmbeddedViewCon
}
protected detectChanges() {
this.getChangeDetectorRef().detectChanges();
if(this.getModel()) {
this.getModel().afterRerender();
}
}

protected getShouldReattachChangeDetector(): boolean {
Expand Down
10 changes: 5 additions & 5 deletions packages/survey-angular-ui/src/questions/ranking.component.html
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
<div *ngIf="!model.selectToRankEnabled" [class]="model.rootClass" #contentElement>
<ng-container *ngFor="let item of model.rankingChoices; index as index; trackBy: trackItemBy">
<ng-container *ngFor="let item of model.renderedRankingChoices; index as index; trackBy: trackItemBy">
<ng-template [component]="{ name: getItemValueComponentName(item), data: getItemValueComponentData(item, index) }"></ng-template>
</ng-container>
</div>

<div *ngIf="model.selectToRankEnabled" [class]="model.rootClass" #contentElement>
<div [class]='model.getContainerClasses("from")' data-ranking="from-container">
<ng-container *ngFor="let item of model.unRankingChoices; index as index; trackBy: trackItemBy">
<ng-container *ngFor="let item of model.renderedUnRankingChoices; index as index; trackBy: trackItemBy">
<ng-template [component]="{ name: getItemValueComponentName(item), data: getItemValueComponentData(item, index, true) }"></ng-template>
</ng-container>

<div *ngIf="model.unRankingChoices.length === 0" [class]="model.cssClasses.containerPlaceholder" [model]="$any(model).locSelectToRankEmptyRankedAreaText" sv-ng-string></div>
<div *ngIf="model.renderedUnRankingChoices.length === 0" [class]="model.cssClasses.containerPlaceholder" [model]="$any(model).locSelectToRankEmptyRankedAreaText" sv-ng-string></div>
</div>

<div [class]="model.cssClasses.containersDivider"></div>

<div [class]='model.getContainerClasses("to")' data-ranking="to-container">
<ng-container *ngFor="let item of model.rankingChoices; index as index; trackBy: trackItemBy">
<ng-container *ngFor="let item of model.renderedRankingChoices; index as index; trackBy: trackItemBy">
<ng-template [component]="{ name: getItemValueComponentName(item), data: getItemValueComponentData(item, index) }"></ng-template>
</ng-container>

<div *ngIf="model.rankingChoices.length === 0" [class]="model.cssClasses.containerPlaceholder" [model]="$any(model).locSelectToRankEmptyUnrankedAreaText" sv-ng-string></div>
<div *ngIf="model.renderedRankingChoices.length === 0" [class]="model.cssClasses.containerPlaceholder" [model]="$any(model).locSelectToRankEmptyUnrankedAreaText" sv-ng-string></div>
</div>
</div>
10 changes: 6 additions & 4 deletions packages/survey-vue3-ui/src/MatrixDropdownCellComp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,18 @@ const getCellStyle = () => {
return null;
};
const getCellIndex = () => (props.cell as any).index || "";
const onVisibilityChanged = () =>
(isVisible.value = props.cell.question.isVisible);
const onVisibilityChanged = () => {
if (!props.cell.hasQuestion || !props.question || !props.question.survey)
return;
isVisible.value = props.cell.question.isVisible;
};
const getComponentName = (element: Question | any) => {
return getComponent(element);
};

onVisibilityChanged();
onMounted(() => {
if (!props.cell.hasQuestion || !props.question || !props.question.survey)
return;
onVisibilityChanged();
props.cell.question.registerPropertyChangedHandlers(["isVisible"], () => {
onVisibilityChanged();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-vue3-ui/src/Question.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<component :is="contentComponentName" v-bind="contentComponentData">
<div
:class="getContentClass(element) || undefined"
v-show="element.renderedIsExpanded"
:style="{ display: !element.renderedIsExpanded ? 'none' : undefined }"
role="presentation"
>
<survey-errors
Expand Down
18 changes: 11 additions & 7 deletions packages/survey-vue3-ui/src/Ranking.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div :class="question.rootClass" ref="root">
<template v-if="!question.selectToRankEnabled">
<component
v-for="(item, index) in question.rankingChoices"
v-for="(item, index) in question.renderedRankingChoices"
:key="item.value + '-' + index + '-item'"
:is="getItemValueComponentName(item)"
v-bind="getItemValueComponentData(item, index)"
Expand All @@ -15,17 +15,19 @@
data-ranking="from-container"
>
<component
v-for="(item, index) in question.unRankingChoices"
v-for="(item, index) in question.renderedUnRankingChoices"
:key="item.value + '-' + index + '-item'"
:is="getItemValueComponentName(item)"
v-bind="getItemValueComponentData(item, index, true)"
></component>

<div
v-if="question.unRankingChoices.length === 0"
v-if="question.renderedUnRankingChoices.length === 0"
:class="question.cssClasses.containerPlaceholder"
>
<survey-string :locString="question.locSelectToRankEmptyRankedAreaText"></survey-string>
<survey-string
:locString="question.locSelectToRankEmptyRankedAreaText"
></survey-string>
</div>
</div>

Expand All @@ -40,17 +42,19 @@
data-ranking="to-container"
>
<component
v-for="(item, index) in question.rankingChoices"
v-for="(item, index) in question.renderedRankingChoices"
:key="item.value + '-' + index + '-item'"
:is="getItemValueComponentName(item)"
v-bind="getItemValueComponentData(item, index)"
></component>

<div
v-if="question.rankingChoices.length === 0"
v-if="question.renderedRankingChoices.length === 0"
:class="question.cssClasses.containerPlaceholder"
>
<survey-string :locString="question.locSelectToRankEmptyUnrankedAreaText"></survey-string>
<survey-string
:locString="question.locSelectToRankEmptyUnrankedAreaText"
></survey-string>
</div>
</div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions packages/survey-vue3-ui/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {
type Ref,
onBeforeUnmount,
watchEffect,
nextTick,
onBeforeUpdate,
onUpdated,
} from "vue";
Base.createPropertiesHash = () => {
const res = shallowReactive({});
Expand Down Expand Up @@ -51,6 +54,7 @@ export function makeReactive(surveyElement: Base) {
}
};
}
surveyElement.enableOnElementRenderedEvent();
(surveyElement as any).__vueImplemented++;
}

Expand Down Expand Up @@ -94,6 +98,9 @@ export function useBase<T extends Base>(
immediate: true,
}
);
onUpdated(() => {
getModel().afterRerender();
});
onBeforeUnmount(() => {
const model = getModel();
if (model) {
Expand Down
3 changes: 2 additions & 1 deletion src/base-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ export interface ISurvey extends ITextProcessor, ISurveyErrorOwner {
element: ISurveyElement,
question: IQuestion,
page: IPage,
id: string, scrollIfVisible?: boolean
id: string, scrollIfVisible?: boolean,
scrollIntoViewOptions?: ScrollIntoViewOptions
): any;
runExpression(expression: string): any;
elementContentVisibilityChanged(element: ISurveyElement): void;
Expand Down
23 changes: 20 additions & 3 deletions src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,7 @@ export class Base {
return this.getIsAnimationAllowed();
}
protected getIsAnimationAllowed(): boolean {
return settings.animationEnabled && this.animationAllowedLock >= 0 && !this.isLoadingFromJson && !this.isDisposed;
return settings.animationEnabled && this.animationAllowedLock >= 0 && !this.isLoadingFromJson && !this.isDisposed && (!!this.onElementRerendered || !this.supportOnElementRenderedEvent);
}
private animationAllowedLock: number = 0;
public blockAnimations(): void {
Expand All @@ -1158,6 +1158,22 @@ export class Base {
public releaseAnimations(): void {
this.animationAllowedLock++;
}
//remove when knockout obsolete
public supportOnElementRenderedEvent = true;
public onElementRenderedEventEnabled = false;
public enableOnElementRenderedEvent(): void {
this.onElementRenderedEventEnabled = true;
}
public disableOnElementRenderedEvent(): void {
this.onElementRenderedEventEnabled = false;
}
protected _onElementRerendered: EventBase<Base> = new EventBase();
public get onElementRerendered(): EventBase<Base> {
return this.supportOnElementRenderedEvent && this.onElementRenderedEventEnabled ? this._onElementRerendered : undefined;
}
public afterRerender(): void {
this.onElementRerendered.fire(this, undefined);
}
}

export class ArrayChanges<T = any> {
Expand Down Expand Up @@ -1187,8 +1203,9 @@ export class Event<CallbackFunction extends Function, Sender, Options> {
}
public fire(sender: Sender, options: Options): void {
if (!this.callbacks) return;
for (var i = 0; i < this.callbacks.length; i++) {
this.callbacks[i](sender, options);
const callbacks = [].concat(this.callbacks);
for (var i = 0; i < callbacks.length; i++) {
callbacks[i](sender, options);
if (!this.callbacks) return;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/defaultCss/defaultV2Css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export var defaultV2Css = {
rowMultiple: "sd-row--multiple",
rowCompact: "sd-row--compact",
rowFadeIn: "sd-row--fade-in",
rowDelayedFadeIn: "sd-row--delayed-fade-in",
rowFadeOut: "sd-row--fade-out",
pageRow: "sd-page__row",
question: {
Expand Down
14 changes: 13 additions & 1 deletion src/defaultV2-theme/blocks/sd-row.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,19 @@
margin-top: var(--sd-base-vertical-padding);
--animate-margin: var(--sd-base-vertical-padding);
}
& ~ .sd-page__row.sd-row.sd-row--fade-in.sd-row--fade-in {
margin-top: 0;
}
}

.sd-row.sd-page__row:not(.sd-row--compact) {
& ~ .sd-row.sd-page__row:not(.sd-row--compact) {
margin-top: calcSize(2);
--animate-margin: #{calcSize(2)};
}
& ~ .sd-page__row.sd-row.sd-row--fade-in.sd-row--fade-in {
margin-top: 0;
}
}

.sd-row--multiple {
Expand Down Expand Up @@ -112,16 +118,22 @@
margin-top: var(--animate-margin);
}
}

.sd-row.sd-row--fade-in {
margin-top: 0;
}
.sd-row--fade-in {
animation-fill-mode: forwards;
animation-name: fadeIn, moveInWithOverflow, marginFadeIn;
min-height: 0 !important;
opacity: 0;
height: 0;
animation-timing-function: $ease-out;
animation-delay: $row-fade-in-delay, 0s, 0s;
animation-duration: $row-fade-in-duration, $row-move-in-duration, $row-move-in-duration;
}
.sd-row--delayed-fade-in {
animation-delay: calc(#{$row-fade-in-delay} + #{$row-fade-in-animation-delay}), $row-fade-in-animation-delay, $row-fade-in-animation-delay;
}

.sd-row--fade-out {
animation-name: fadeIn, moveInWithOverflow, marginFadeIn;
Expand Down
1 change: 1 addition & 0 deletions src/defaultV2-theme/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ $row-fade-in-delay: var(--sjs-row-fade-in-delay, 150ms);
$row-fade-out-duration: var(--sjs-row-fade-out-duration, 150ms);
$row-move-out-duration: var(--sjs-row-move-out-duration, 250ms);
$row-move-out-delay: var(--sjs-row-move-out-delay, 100ms);
$row-fade-in-animation-delay: var(--sjs-row-fade-in-animation-delay, 400ms);

$expand-fade-in-duration: var(--sjs-expand-fade-in-duration, 500ms);
$expand-move-in-duration: var(--sjs-expand-move-in-duration, 150ms);
Expand Down
Loading
Loading