Skip to content

Commit

Permalink
Ignore disable items in select all, fix #7465, #7466 (#7469)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtelnov authored Dec 7, 2023
1 parent 1e9ed29 commit c90aa0e
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 30 deletions.
78 changes: 48 additions & 30 deletions src/question_checkbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,20 @@ export class QuestionCheckboxModel extends QuestionCheckboxBase {
* @see showSelectAllItem
*/
public get isAllSelected(): boolean {
var val = this.value;
if (!val || !Array.isArray(val)) return false;
if (this.isItemSelected(this.noneItem)) return false;
var allItemCount = this.visibleChoices.length;
const order = settings.specialChoicesOrder;
if (this.hasOther) allItemCount -= order.otherItem.length;
if (this.hasNone) allItemCount -= order.noneItem.length;
if (this.hasSelectAll) allItemCount -= order.selectAllItem.length;
var selectedCount = val.length;
if (this.isOtherSelected) selectedCount--;
return selectedCount === allItemCount;
const items = this.getVisibleEnableItems();
if(items.length === 0) return false;
const val = this.value;
if (!val || !Array.isArray(val) || val.length === 0) return false;
if(val.length < items.length) return false;
const rVal = [];
for(let i = 0; i < val.length; i ++) {
rVal.push(this.getRealValue(val[i]));
}
for(let i = 0; i < items.length; i ++) {
if(rVal.indexOf(items[i].value) < 0) return false;
}
return true;
}
public set isAllSelected(val: boolean) {
if (val) {
Expand All @@ -132,7 +135,7 @@ export class QuestionCheckboxModel extends QuestionCheckboxBase {
this.clearValue();
}
}
public toggleSelectAll() {
public toggleSelectAll(): void {
this.isAllSelected = !this.isAllSelected;
}
/**
Expand All @@ -142,16 +145,10 @@ export class QuestionCheckboxModel extends QuestionCheckboxBase {
* @see clearValue
*/
public selectAll(): void {
var val: Array<any> = [];
for (var i = 0; i < this.visibleChoices.length; i++) {
var item = this.visibleChoices[i];
if (
item === this.noneItem ||
item === this.otherItem ||
item === this.selectAllItem
)
continue;
val.push(item.value);
const val: Array<any> = [];
const items = this.getVisibleEnableItems();
for (let i = 0; i < items.length; i++) {
val.push(items[i].value);
}
this.renderedValue = val;
}
Expand Down Expand Up @@ -245,7 +242,7 @@ export class QuestionCheckboxModel extends QuestionCheckboxBase {
protected onCheckForErrors(
errors: Array<SurveyError>,
isOnValueChanged: boolean
):void {
): void {
super.onCheckForErrors(errors, isOnValueChanged);
if (isOnValueChanged) return;

Expand All @@ -257,28 +254,49 @@ export class QuestionCheckboxModel extends QuestionCheckboxBase {
errors.push(minError);
}
}

protected onVisibleChoicesChanged(): void {
super.onVisibleChoicesChanged();
this.updateSelectAllItemProps();
}
protected onEnableItemCallBack(item: ItemValue): boolean {
if (!this.shouldCheckMaxSelectedChoices()) return true;
return this.isItemSelected(item);
}
protected onAfterRunItemsEnableCondition() {
protected onAfterRunItemsEnableCondition(): void {
this.updateSelectAllItemProps();
if (this.maxSelectedChoices < 1) {
this.selectAllItem.setIsEnabled(true);
this.otherItem.setIsEnabled(true);
return;
}
if (this.hasSelectAll) {
this.selectAllItem.setIsEnabled(
this.maxSelectedChoices >= this.activeChoices.length
);
}
if (this.hasOther) {
this.otherItem.setIsEnabled(
!this.shouldCheckMaxSelectedChoices() || this.isOtherSelected
);
}
}
private updateSelectAllItemProps(): void {
if (!this.hasSelectAll) return;
this.selectAllItem.setIsEnabled(this.getSelectAllEnabled());
}
private getSelectAllEnabled(): boolean {
if (!this.hasSelectAll) return true;
const items = this.activeChoices;
let visCount = this.getVisibleEnableItems().length;
const max = this.maxSelectedChoices;
if(max > 0 && max < visCount) return false;
return visCount > 0;
}
private getVisibleEnableItems(): Array<ItemValue> {
const res = new Array<ItemValue>();
const items = this.activeChoices;
for(let i = 0; i < items.length; i ++) {
const item = items[i];
if(item.isEnabled && item.isVisible) {
res.push(item);
}
}
return res;
}
private shouldCheckMaxSelectedChoices(): boolean {
if (this.maxSelectedChoices < 1) return false;
var val = this.value;
Expand Down
60 changes: 60 additions & 0 deletions tests/question_baseselecttests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1500,3 +1500,63 @@ QUnit.test("Double noneItem & selectAllItem and headItems/footItems", function (
settings.specialChoicesOrder.noneItem = [1];
settings.specialChoicesOrder.otherItem = [2];
});
QUnit.test("Select all disable/enabled", function (assert) {
const json = { elements: [
{ type: "checkbox", name: "q1",
choices: [{ value: "a", visibleIf: "{val1}=1" }, { value: "b", enableIf: "{val2}=1" }],
showSelectAllItem: true, showNoneItem: true }
] };
const survey = new SurveyModel(json);
const question = <QuestionCheckboxModel>survey.getQuestionByName("q1");
const selectAll = question.selectAllItem;
assert.equal(selectAll.isEnabled, false, "#1");
assert.equal(question.isItemSelected(selectAll), false, "#1.1");
survey.setVariable("val1", 1);
assert.equal(selectAll.isEnabled, true, "#2");
assert.equal(question.isItemSelected(selectAll), false, "#2.1");
survey.setVariable("val1", 2);
assert.equal(selectAll.isEnabled, false, "#3");
assert.equal(question.isItemSelected(selectAll), false, "#3.1");
survey.setVariable("val2", 1);
assert.equal(selectAll.isEnabled, true, "#4");
assert.equal(question.isItemSelected(selectAll), false, "#4.1");
survey.setVariable("val2", 2);
assert.equal(selectAll.isEnabled, false, "#5");
assert.equal(question.isItemSelected(selectAll), false, "#5.1");
});
QUnit.test("question.selectAll() disable/enabled and visible", function (assert) {
const json = { elements: [
{ type: "checkbox", name: "q1",
choices: [{ value: "a", visibleIf: "{val1}=1" }, { value: "b", enableIf: "{val2}=1" }, "c"],
showSelectAllItem: true, showNoneItem: true }
] };
const survey = new SurveyModel(json);
const question = <QuestionCheckboxModel>survey.getQuestionByName("q1");
const selectAll = question.selectAllItem;
assert.equal(question.isItemSelected(selectAll), false, "#1.1");
question.selectAll();
assert.deepEqual(question.value, ["c"], "#1.2");
assert.equal(question.isItemSelected(selectAll), true, "#1.3");

survey.setVariable("val1", 1);
assert.equal(question.isItemSelected(selectAll), false, "#2.1");
question.selectAll();
assert.deepEqual(question.value, ["a", "c"], "#2.2");
assert.equal(question.isItemSelected(selectAll), true, "#2.3");

survey.setVariable("val2", 1);
assert.equal(question.isItemSelected(selectAll), false, "#3.1");
question.selectAll();
assert.deepEqual(question.value, ["a", "b", "c"], "#3.2");
assert.equal(question.isItemSelected(selectAll), true, "#3.3");
});
QUnit.test("Select all disable/enabled showOtherItem=true", function (assert) {
const json = { elements: [
{ type: "checkbox", name: "q1", showSelectAllItem: true, showOtherItem: true }
] };
const survey = new SurveyModel(json);
const question = <QuestionCheckboxModel>survey.getQuestionByName("q1");
const selectAll = question.selectAllItem;
assert.equal(selectAll.isEnabled, false, "#1");
assert.equal(question.isItemSelected(selectAll), false, "#2");
});

0 comments on commit c90aa0e

Please sign in to comment.