Skip to content

Commit

Permalink
Custom Components - Question input is not highlighted when a validati…
Browse files Browse the repository at this point in the history
…on error occurs fix #7180
  • Loading branch information
andrewtelnov committed Oct 18, 2023
1 parent ff35c9e commit 655357b
Show file tree
Hide file tree
Showing 12 changed files with 39 additions and 16 deletions.
14 changes: 9 additions & 5 deletions src/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export class Question extends SurveyElement<Question>
focusCallback: () => void;
surveyLoadCallback: () => void;
displayValueCallback: (text: string) => string;
hasCssErrorCallback: () => boolean = (): boolean => false;

private defaultValueRunner: ExpressionRunner;
private isChangingViaDefaultValue: boolean;
Expand Down Expand Up @@ -962,7 +963,7 @@ export class Question extends SurveyElement<Question>
this.setPropertyValue("cssRoot", val);
}
protected getCssRoot(cssClasses: { [index: string]: string }): string {
const hasError = this.errors.length > 0;
const hasError = this.hasCssError();
return new CssClassBuilder()
.append(super.getCssRoot(cssClasses))
.append(this.isFlowLayout && !this.isDesignMode
Expand Down Expand Up @@ -1071,6 +1072,9 @@ export class Question extends SurveyElement<Question>
.append(cssClasses.error.locationBottom, this.showErrorOnBottom)
.toString();
}
protected hasCssError(): boolean {
return this.errors.length > 0 || this.hasCssErrorCallback();
}
public getRootCss(): string {
return new CssClassBuilder()
.append(this.cssRoot)
Expand Down Expand Up @@ -2538,7 +2542,7 @@ export class Question extends SurveyElement<Question>
public get ariaInvalid() {
if (this.isNewA11yStructure) return null;

return this.errors.length > 0 ? "true" : "false";
return this.hasCssError() ? "true" : "false";
}
public get ariaLabelledBy(): string {
if (this.isNewA11yStructure) return null;
Expand All @@ -2555,7 +2559,7 @@ export class Question extends SurveyElement<Question>
public get ariaDescribedBy(): string {
if (this.isNewA11yStructure) return null;

return this.errors.length > 0 ? this.id + "_errors" : null;
return this.hasCssError() ? this.id + "_errors" : null;
}
//EO a11y

Expand All @@ -2567,7 +2571,7 @@ export class Question extends SurveyElement<Question>
return this.isRequired ? "true" : "false";
}
public get a11y_input_ariaInvalid(): "true" | "false" {
return this.errors.length > 0 ? "true" : "false";
return this.hasCssError() ? "true" : "false";
}
public get a11y_input_ariaLabel(): string {
if (this.hasTitle && !this.parentQuestion) {
Expand All @@ -2584,7 +2588,7 @@ export class Question extends SurveyElement<Question>
}
}
public get a11y_input_ariaDescribedBy(): string {
return this.errors.length > 0 ? this.id + "_errors" : null;
return this.hasCssError() ? this.id + "_errors" : null;
}
//EO new a11y
}
Expand Down
2 changes: 1 addition & 1 deletion src/question_baseselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1541,7 +1541,7 @@ export class QuestionSelectBase extends Question {
.append(this.cssClasses.item)
.append(this.cssClasses.itemInline, !this.hasColumns && this.colCount === 0)
.append("sv-q-col-" + this.getCurrentColCount(), !this.hasColumns && this.colCount !== 0)
.append(this.cssClasses.itemOnError, this.errors.length > 0);
.append(this.cssClasses.itemOnError, this.hasCssError());

const isDisabled = this.isReadOnly || !item.isEnabled;
const isChecked = this.isItemSelected(item) ||
Expand Down
2 changes: 1 addition & 1 deletion src/question_boolean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export class QuestionBooleanModel extends Question {
private getItemCssValue(css: any): string {
return new CssClassBuilder()
.append(css.item)
.append(css.itemOnError, this.errors.length > 0)
.append(css.itemOnError, this.hasCssError())
.append(css.itemDisabled, this.isReadOnly)
.append(css.itemHover, !this.isDesignMode)
.append(css.itemChecked, !!this.booleanValue)
Expand Down
1 change: 1 addition & 0 deletions src/question_custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,7 @@ export class QuestionCustomModel extends QuestionCustomModelBase {
res.onUpdateCssClassesCallback = (css: any): void => {
this.onUpdateQuestionCssClasses(res, css);
};
res.hasCssErrorCallback = (): boolean => this.errors.length > 0;
}

return res;
Expand Down
2 changes: 1 addition & 1 deletion src/question_dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export class QuestionDropdownModel extends QuestionSelectBase {
return new CssClassBuilder()
.append(this.cssClasses.control)
.append(this.cssClasses.controlEmpty, this.isEmpty())
.append(this.cssClasses.onError, this.errors.length > 0)
.append(this.cssClasses.onError, this.hasCssError())
.append(this.cssClasses.controlDisabled, this.isReadOnly)
.append(this.cssClasses.controlInputFieldComponent, !!this.inputFieldComponentName)
.toString();
Expand Down
2 changes: 1 addition & 1 deletion src/question_file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ export class QuestionFileModel extends Question {
public getFileDecoratorCss(): string {
return new CssClassBuilder()
.append(this.cssClasses.fileDecorator)
.append(this.cssClasses.onError, this.errors.length > 0)
.append(this.cssClasses.onError, this.hasCssError())
.append(this.cssClasses.fileDecoratorDrag, this.isDragging)
.toString();
}
Expand Down
4 changes: 2 additions & 2 deletions src/question_matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ export class QuestionMatrixModel
return new CssClassBuilder()
.append(this.cssClasses.cell, this.hasCellText)
.append(this.hasCellText ? this.cssClasses.cellText : this.cssClasses.label)
.append(this.cssClasses.itemOnError, !this.hasCellText && this.errors.length > 0)
.append(this.cssClasses.itemOnError, !this.hasCellText && this.hasCssError())
.append(this.hasCellText ? this.cssClasses.cellTextSelected : this.cssClasses.itemChecked, isChecked)
.append(this.hasCellText ? this.cssClasses.cellTextDisabled : this.cssClasses.itemDisabled, isDisabled)
.append(this.cssClasses.itemHover, allowHover && !this.hasCellText)
Expand Down Expand Up @@ -419,7 +419,7 @@ export class QuestionMatrixModel
) {
super.onCheckForErrors(errors, isOnValueChanged);
if (
(!isOnValueChanged || this.errors.length > 0) &&
(!isOnValueChanged || this.hasCssError()) &&
this.hasErrorInRows()
) {
errors.push(new RequiredInAllRowsError(null, this));
Expand Down
2 changes: 1 addition & 1 deletion src/question_ranking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class QuestionRankingModel extends QuestionCheckboxModel {
.append(this.cssClasses.rootMobileMod, IsMobile)
.append(this.cssClasses.rootDisabled, this.isReadOnly)
.append(this.cssClasses.rootDesignMode, !!this.isDesignMode)
.append(this.cssClasses.itemOnError, this.errors.length > 0)
.append(this.cssClasses.itemOnError, this.hasCssError())
.append(this.cssClasses.rootDragHandleAreaIcon, settings.rankingDragHandleArea === "icon")
.append(this.cssClasses.rootSelectToRankMod, this.selectToRankEnabled)
.append(this.cssClasses.rootSelectToRankAlignHorizontal, this.selectToRankEnabled && this.selectToRankAreasLayout === "horizontal")
Expand Down
4 changes: 2 additions & 2 deletions src/question_rating.ts
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ export class QuestionRatingModel extends Question {
.append(itemScaleColoredClass, this.scaleColorMode == "colored")
.append(itemRateColoredClass, this.rateColorMode == "scale" && isSelected)
.append(itemUnhighlightedClass, isUnhighlighted)
.append(itemitemOnErrorClass, this.errors.length > 0)
.append(itemitemOnErrorClass, this.hasCssError())
.append(itemSmallClass, this.itemSmallMode)
.append(this.cssClasses.itemFixedSize, hasFixedSize)
.toString();
Expand All @@ -737,7 +737,7 @@ export class QuestionRatingModel extends Question {
return new CssClassBuilder()
.append(this.cssClasses.control)
.append(this.cssClasses.controlEmpty, this.isEmpty())
.append(this.cssClasses.onError, this.errors.length > 0)
.append(this.cssClasses.onError, this.hasCssError())
.append(this.cssClasses.controlDisabled, this.isReadOnly)
.toString();
}
Expand Down
2 changes: 1 addition & 1 deletion src/question_tagbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export class QuestionTagboxModel extends QuestionCheckboxModel {
return new CssClassBuilder()
.append(this.cssClasses.control)
.append(this.cssClasses.controlEmpty, this.isEmpty())
.append(this.cssClasses.onError, this.errors.length > 0)
.append(this.cssClasses.onError, this.hasCssError())
.append(this.cssClasses.controlDisabled, this.isReadOnly)
.toString();
}
Expand Down
2 changes: 1 addition & 1 deletion src/question_textbase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class QuestionTextBase extends Question {
public getControlClass(): string {
return new CssClassBuilder()
.append(this.cssClasses.root)
.append(this.cssClasses.onError, this.errors.length > 0)
.append(this.cssClasses.onError, this.hasCssError())
.append(this.cssClasses.controlDisabled, this.isReadOnly)
.toString();
}
Expand Down
18 changes: 18 additions & 0 deletions tests/question_customtests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2392,3 +2392,21 @@ QUnit.test("Complex: onHidingContent", function (assert) {
assert.equal(counter, 2, "onComplete");
ComponentCollection.Instance.clear();
});
QUnit.test("Single: Apply error css", function (assert) {
const json = {
name: "newquestion",
questionJSON: { type: "text" },
};
ComponentCollection.Instance.add(json);
const survey = new SurveyModel({
elements: [{ type: "newquestion", name: "q1", isRequired: true }],
});
const q = <QuestionCustomModel>survey.getAllQuestions()[0];
const qText = <QuestionTextModel>q.contentQuestion;
const errorCss = qText.cssClasses.onError;
assert.ok(errorCss, "error css is not empty");
assert.equal(qText.getControlClass().indexOf(errorCss) < 0, true, "errors is not here");
q.validate(true);
assert.equal(qText.getControlClass().indexOf(errorCss) > -1, true, "errors is here");
ComponentCollection.Instance.clear();
});

0 comments on commit 655357b

Please sign in to comment.