Skip to content

Commit

Permalink
Implement help methods for creator's d&d pages animation (#9017)
Browse files Browse the repository at this point in the history
* Do not update page while deleting (animation)

* Add callback for control group animation

* Refactor onCompareArrays callback

* Small refactor for vue3

* Implement block ui changes in angular

* Fix rows updates while deleting page

* Remove blockUpdates method. Clean page only after unmount

* Revert "Small refactor for vue3"

This reverts commit 649e57b.

* Remove QUnit.only

* Refactor
  • Loading branch information
dk981234 authored Nov 8, 2024
1 parent f2b13b8 commit 667bad6
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 8 deletions.
21 changes: 21 additions & 0 deletions packages/survey-core/src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,27 @@ export class PageModel extends PanelModelBase implements IPage {
super.ensureRowsVisibility();
this.getPanels().forEach((panel) => panel.ensureRowsVisibility());
}

private _isReadyForClean: boolean = true;
public get isReadyForClean(): boolean {
return this._isReadyForClean;
}
public set isReadyForClean(val: boolean) {
const oldValue = this._isReadyForClean;
this._isReadyForClean = val;
if(this._isReadyForClean !== oldValue) {
this.isReadyForCleanChangedCallback && this.isReadyForCleanChangedCallback();
}
}
public isReadyForCleanChangedCallback: () => void;
public enableOnElementRerenderedEvent(): void {
super.enableOnElementRerenderedEvent();
this.isReadyForClean = false;
}
public disableOnElementRerenderedEvent(): void {
super.disableOnElementRerenderedEvent();
this.isReadyForClean = true;
}
}

Serializer.addClass(
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-core/src/question_ranking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export class QuestionRankingModel extends QuestionCheckboxModel {
this.value = newValue;
}

private getChoicesAnimationOptions(isRankingChoices: boolean): Required<IAnimationGroupConsumer<ItemValue>> {
private getChoicesAnimationOptions(isRankingChoices: boolean): IAnimationGroupConsumer<ItemValue> {
return {
getKey(item: ItemValue) {
return item.value;
Expand Down
17 changes: 14 additions & 3 deletions packages/survey-core/src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -905,13 +905,24 @@ export class SurveyModel extends SurveyElementCore
this.timerModelValue.onTimerTick = (page: PageModel): void => {
this.doTimer(page);
};

this.createNewArray(
"pages",
(value: any) => {
(value: PageModel) => {
if(value.isReadyForCleanChangedCallback) {
value.isReadyForCleanChangedCallback();
}
this.doOnPageAdded(value);
},
(value: any) => {
this.doOnPageRemoved(value);
(value: PageModel) => {
if(!value.isReadyForClean) {
value.isReadyForCleanChangedCallback = () => {
this.doOnPageRemoved(value);
value.isReadyForCleanChangedCallback = undefined;
};
} else {
this.doOnPageRemoved(value);
}
}
);
this.createNewArray("triggers", (value: any) => {
Expand Down
20 changes: 16 additions & 4 deletions packages/survey-core/src/utils/animation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,18 @@ interface IGroupAnimationInfo {
isDeletingRunning: boolean;
isAddingRunning: boolean;
}
interface IGroupAnimationCompareInfo<T> {
addedItems: Array<T>;
deletedItems: Array<T>;
reorderedItems: Array<{ item: T, movedForward: boolean}>;
mergedItems: Array<T>;
}
export interface IAnimationGroupConsumer<T> extends IAnimationConsumer<[T]> {
getLeaveOptions?(item: T, info? : IGroupAnimationInfo): AnimationOptions;
getEnterOptions?(item: T, info?: IGroupAnimationInfo): AnimationOptions;
getReorderOptions?(item: T, movedForward: boolean, info?: IGroupAnimationInfo): AnimationOptions;
getKey?: (item: T) => any;
onCompareArrays?(options: IGroupAnimationCompareInfo<T>): void;
allowSyncRemovalAddition?: boolean;
}

Expand Down Expand Up @@ -316,11 +323,16 @@ export class AnimationGroup<T> extends AnimationProperty<Array<T>, IAnimationGro
newValue = [].concat(newValue);
const oldValue = [].concat(this.getCurrentValue());
const allowSyncRemovalAddition = this.animationOptions.allowSyncRemovalAddition ?? true;
let { addedItems, deletedItems, reorderedItems, mergedItems } = compareArrays(oldValue, newValue, this.animationOptions.getKey ?? ((item: T) => item));
if(!allowSyncRemovalAddition && (reorderedItems.length > 0 || addedItems.length > 0)) {
deletedItems = [];
mergedItems = newValue;
let compareResult = compareArrays(oldValue, newValue, this.animationOptions.getKey ?? ((item: T) => item));

if(!allowSyncRemovalAddition && (compareResult.reorderedItems.length > 0 || compareResult.addedItems.length > 0)) {
compareResult.deletedItems = [];
compareResult.mergedItems = newValue;
}
if(!!this.animationOptions.onCompareArrays) {
this.animationOptions.onCompareArrays(compareResult);
}
let { addedItems, reorderedItems, deletedItems, mergedItems } = compareResult;
const runAnimationCallback = () => {
this.animation.runGroupAnimation(this.animationOptions, addedItems, deletedItems, reorderedItems, () => {
if(deletedItems.length > 0) {
Expand Down
45 changes: 45 additions & 0 deletions packages/survey-core/tests/surveytests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20700,6 +20700,51 @@ QUnit.test("Check that focusInput works correctly with shadow dom", function (as
assert.equal(root.shadowRoot?.activeElement, input);
root.remove();
});
QUnit.test("Check page is cleared only after unmount", function (assert) {
const survey = new SurveyModel({
pages: [
{
name: "p1",
elements: [
{ type: "text", name: "q1" },
]
},
{
name: "p2",
elements: [
{ type: "text", name: "q2" },
]
},
{
name: "p3",
elements: [
{ type: "text", name: "q3" },
]
}
]
});
const page1 = survey.getPageByName("p1");
page1.supportOnElementRerenderedEvent = true;
page1.enableOnElementRerenderedEvent();
survey.removePage(page1);
assert.ok(!!page1.survey);
page1.disableOnElementRerenderedEvent();
assert.notOk(!!page1.survey);

const page2 = survey.getPageByName("p2");
page2.supportOnElementRerenderedEvent = true;
page2.enableOnElementRerenderedEvent();
survey.removePage(page2);
survey.addPage(page2);
assert.ok(!!page2.survey);
page2.disableOnElementRerenderedEvent();
assert.ok(!!page2.survey);

const page3 = survey.getPageByName("p3");
page3.supportOnElementRerenderedEvent = true;
survey.removePage(page3);
assert.notOk(!!page3.survey);
});
QUnit.test("Reduce the number of calls of setVisibleIndexes function", function (assert) {
const survey = new SurveyModel();
survey.setDesignMode(true);
Expand Down

0 comments on commit 667bad6

Please sign in to comment.