Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d2233ea
Refactor calculated values
andrewtelnov Jan 20, 2026
5dc11b4
Refactor matrix base
andrewtelnov Jan 20, 2026
709686d
Refactor choices restful class
andrewtelnov Jan 20, 2026
5fb66a5
Refactor page class
andrewtelnov Jan 20, 2026
6338f05
Revert one property in page class
andrewtelnov Jan 20, 2026
42fe8cd
Refactor panel classes
andrewtelnov Jan 21, 2026
bc21a71
refactor popup-survey class
andrewtelnov Jan 21, 2026
101a7fe
refactor popup class
andrewtelnov Jan 21, 2026
761b224
Fix issues with calculdated function in @property
andrewtelnov Jan 22, 2026
60658a9
Merge branch 'master' into refactor/use-property-decorator
andrewtelnov Jan 22, 2026
15758a9
Refactor base select classes
andrewtelnov Jan 22, 2026
7e5318f
Refactor checkbox class
andrewtelnov Jan 22, 2026
029315d
Refactor comment class
andrewtelnov Jan 22, 2026
3535b5c
Refactor dropdown class
andrewtelnov Jan 22, 2026
db791c9
refactor expression class
andrewtelnov Jan 22, 2026
60e6c6b
refactor file classes
andrewtelnov Jan 22, 2026
a085914
refactor imagemap class
andrewtelnov Jan 22, 2026
999973c
refactor image file
andrewtelnov Jan 22, 2026
00e7426
refactor image picker
andrewtelnov Jan 22, 2026
314e661
refactor single matrix
andrewtelnov Jan 22, 2026
02e0a09
refactor matrix dropdown
andrewtelnov Jan 22, 2026
df5ac99
refactor matrix dropdown base
andrewtelnov Jan 22, 2026
c28bbc6
refactor matrix column
andrewtelnov Jan 22, 2026
ec78ad0
refactor matrix dynamic
andrewtelnov Jan 22, 2026
d35d85a
Replace emptyStr vs returnValue
andrewtelnov Jan 22, 2026
d262a38
refactor multiple text
andrewtelnov Jan 22, 2026
b29e1b3
refactor radiogroup
andrewtelnov Jan 22, 2026
78a5421
refactor panel dynamic
andrewtelnov Jan 22, 2026
9a01d2e
Fix markup tests
andrewtelnov Jan 24, 2026
9ec12b6
Done by AI
andrewtelnov Jan 24, 2026
5857ee3
FIx several properties
andrewtelnov Jan 24, 2026
bfd4b55
refactor question rating
andrewtelnov Jan 25, 2026
2a8ee27
Merge branch 'master' into refactor/use-property-decorator
andrewtelnov Jan 26, 2026
b7de058
Refactor signature pad
andrewtelnov Jan 26, 2026
c917d05
refactor question slider
andrewtelnov Jan 26, 2026
9fc0d91
refactor text question
andrewtelnov Jan 26, 2026
a55729d
refactor text base class
andrewtelnov Jan 26, 2026
ad989ab
Refactor question class
andrewtelnov Jan 26, 2026
7e9258e
Refactor survey elements
andrewtelnov Jan 26, 2026
473f0f1
refactor survey class
andrewtelnov Jan 26, 2026
6b2c2e9
Refactor triggers
andrewtelnov Jan 27, 2026
19fd7d2
Refactor validators
andrewtelnov Jan 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 10 additions & 20 deletions packages/survey-core/src/calculatedValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HashTable, Helpers } from "./helpers";
import { Base } from "./base";
import { ISurvey, ISurveyVariables } from "./base-interfaces";
import { ExpressionRunner } from "./conditions";
import { Serializer } from "./jsonobject";
import { property, Serializer } from "./jsonobject";

/**
* The calculated value is a way to define the variable in Survey Creator.
Expand All @@ -24,6 +24,12 @@ export class CalculatedValue extends Base {
this.expression = expression;
}
}
protected override onPropertyValueChanged(name: string, oldValue: any, newValue: any): void {
super.onPropertyValueChanged(name, oldValue, newValue);
if (name === "expression") {
this.rerunExpression();
}
}
public setOwner(data: ISurveyVariables) {
this.data = data;
this.rerunExpression();
Expand All @@ -42,32 +48,16 @@ export class CalculatedValue extends Base {
/**
* The calculated value name. It should be non empty and unique.
*/
public get name(): string {
return this.getPropertyValue("name") || "";
}
public set name(val: string) {
this.setPropertyValue("name", val);
}
@property() name: string;
/**
* Set this property to true to include the non-empty calculated value into survey result, survey.data property.
*/
public get includeIntoResult(): boolean {
return this.getPropertyValue("includeIntoResult");
}
public set includeIntoResult(val: boolean) {
this.setPropertyValue("includeIntoResult", val);
}
@property() includeIntoResult: boolean;
/**
* The Expression that used to calculate the value. You may use standard operators like +, -, * and /, squares (). Here is the example of accessing the question value {questionname}.
* Example: "({quantity} * {price}) * (100 - {discount}) / 100"
*/
public get expression(): string {
return this.getPropertyValue("expression") || "";
}
public set expression(val: string) {
this.setPropertyValue("expression", val);
this.rerunExpression();
}
@property() expression: string;
public locCalculation() {
this.expressionIsRunning = true;
}
Expand Down
79 changes: 21 additions & 58 deletions packages/survey-core/src/choicesRestful.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Base } from "./base";
import { ITextProcessor, IQuestion, ISurvey } from "./base-interfaces";
import { ItemValue } from "./itemvalue";
import { Serializer, JsonObjectProperty } from "./jsonobject";
import { Serializer, JsonObjectProperty, property } from "./jsonobject";
import { WebRequestError, WebRequestEmptyError } from "./error";
import { IBeforeRequestChoicesOptions, settings } from "./settings";
import { SurveyError } from "./survey-error";
Expand Down Expand Up @@ -143,8 +143,19 @@ export class ChoicesRestful extends Base {
};
protected onPropertyValueChanged(name: string, oldValue: any, newValue: any): void {
super.onPropertyValueChanged(name, oldValue, newValue);
if (name === "url" && this.owner) {
(<Base><any>this.owner).setPropertyValue("isUsingRestful", !!newValue);
if (name === "url") {
if (this.owner) {
(<Base><any>this.owner).setPropertyValue("isUsingRestful", !!newValue);
}
this.isUsingCacheFromUrl = undefined;
if (!newValue) return;
if (newValue.indexOf(ChoicesRestful.cacheText) > -1) {
this.isUsingCacheFromUrl = true;
} else {
if (newValue.indexOf(ChoicesRestful.noCacheText) > -1) {
this.isUsingCacheFromUrl = false;
}
}
}
}
public getSurvey(live: boolean = false): ISurvey {
Expand Down Expand Up @@ -388,21 +399,7 @@ export class ChoicesRestful extends Base {
* @see valueName
* @see titleName
*/
public get url(): string {
return this.getPropertyValue("url") || "";
}
public set url(val: string) {
this.setPropertyValue("url", val);
this.isUsingCacheFromUrl = undefined;
if (!val) return;
if (val.indexOf(ChoicesRestful.cacheText) > -1) {
this.isUsingCacheFromUrl = true;
} else {
if (val.indexOf(ChoicesRestful.noCacheText) > -1) {
this.isUsingCacheFromUrl = false;
}
}
}
@property({ returnValue: "" }) url: string;
/**
* Path to the array of choices. The following path separators are allowed: semicolon `;`, comma `,`.
*
Expand All @@ -420,13 +417,7 @@ export class ChoicesRestful extends Base {
* @see valueName
* @see titleName
*/

public get path(): string {
return this.getPropertyValue("path") || "";
}
public set path(val: string) {
this.setPropertyValue("path", val);
}
@property({ returnValue: "" }) path: string;
/**
* Specifies which property in the obtained data object contains choice values.
*
Expand All @@ -436,52 +427,29 @@ export class ChoicesRestful extends Base {
* @see path
* @see titleName
*/

public get valueName(): string {
return this.getPropertyValue("valueName") || "";
}
public set valueName(val: string) {
this.setPropertyValue("valueName", val);
}
@property({ returnValue: "" }) valueName: string;
/**
* Specifies which property in the obtained data object contains display texts for choices.
*
* @see url
* @see path
* @see valueName
*/

public get titleName(): string {
return this.getPropertyValue("titleName") || "";
}
public set titleName(val: string) {
this.setPropertyValue("titleName", val);
}

@property({ returnValue: "" }) titleName: string;
/**
* Specifies which property in the obtained data object contains image URLs. Used only in [Image Picker](https://surveyjs.io/Examples/Library?id=questiontype-imagepicker) questions.
*
* @see url
* @see path
* @see valueName
*/
public get imageLinkName(): string {
return this.getPropertyValue("imageLinkName") || "";
}
public set imageLinkName(val: string) {
this.setPropertyValue("imageLinkName", val);
}
@property({ returnValue: "" }) imageLinkName: string;
/**
* Specifies whether the service is allowed to return an empty response or an empty array in a response.
*
* Default value: `false`
*/
public get allowEmptyResponse(): boolean {
return this.getPropertyValue("allowEmptyResponse");
}
public set allowEmptyResponse(val: boolean) {
this.setPropertyValue("allowEmptyResponse", val);
}
@property() allowEmptyResponse: boolean;
public get attachOriginalItems(): boolean {
return this.attachData;
}
Expand Down Expand Up @@ -522,12 +490,7 @@ export class ChoicesRestful extends Base {
* }
* ```
*/
public get attachData(): boolean {
return this.getPropertyValue("attachData");
}
public set attachData(val: boolean) {
this.setPropertyValue("attachData", val);
}
@property() attachData: boolean;
public get itemValueType(): string {
if (!this.owner) return "itemvalue";
var prop = Serializer.findProperty(this.owner.getType(), "choices");
Expand Down
7 changes: 1 addition & 6 deletions packages/survey-core/src/expressionItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,7 @@ export class ExpressionItem extends Base implements ILocalizableOwner {
/**
* The expression property. If this expression returns true, then survey will use html property to show on complete page.
*/
public get expression(): string {
return this.getPropertyValue("expression", "");
}
public set expression(val: string) {
this.setPropertyValue("expression", val);
}
@property({ returnValue: "" }) expression: string;
get locHtml(): LocalizableString {
return this.getLocalizableString("html");
}
Expand Down
9 changes: 2 additions & 7 deletions packages/survey-core/src/flowpanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,8 @@ export class FlowPanelModel extends PanelModel {
super.onSurveyLoad();
this.onContentChanged();
}
@property({ localizable: true }) content;
public get html(): string {
return this.getPropertyValue("html", "");
}
public set html(val: string) {
this.setPropertyValue("html", val);
}
@property({ localizable: true }) content: string;
@property ({ returnValue: "" }) html: string;
protected onContentChanged(): any {
var html = "";
if (!!this.onCustomHtmlProducing) {
Expand Down
3 changes: 1 addition & 2 deletions packages/survey-core/src/itemvalue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,7 @@ export class ItemValue extends BaseAction implements ILocalizableOwner, IShortcu
}
protected setLocTitle(val: LocalizableString): void {}
protected setTitle(val: string): void {}
public get icon(): string { return this.getPropertyValue("icon", ""); }
public set icon(val: string) { this.setPropertyValue("icon", val); }
@property({ defaultValue: "" }) icon: string;
}

Base.createItemValue = function (source: any, type?: string): any {
Expand Down
25 changes: 22 additions & 3 deletions packages/survey-core/src/jsonobject.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { getLocaleString } from "./surveyStrings";
import { Base, ComputedUpdater } from "./base";
import { Helpers, HashTable } from "./helpers";
import { ILoadFromJSONOptions, ISaveToJSONOptions } from "./base-interfaces";
Expand All @@ -8,10 +7,14 @@ export interface IPropertyDecoratorOptions<T = any> {
defaultValue?: T;
defaultSource?: string;
getDefaultValue?: (objectInstance?: any) => T;
calcFunc?: (objectInstance?: any) => T;
returnValue?: T;
localizable?:
| { name?: string, onCreate?: (obj: Base, locStr: any) => void, defaultStr?: string | boolean, markdown?: boolean }
| boolean;
onSet?: (val: T, objectInstance: any, prevVal?: T) => void;
onSetting?: (val: T, objectInstance: any, prevVal?: T) => T;
isLowerCase?: boolean;
}
function getLocalizablePropertyName(propertyName: string): string {
return "loc" + propertyName.charAt(0).toUpperCase() + propertyName.slice(1);
Expand Down Expand Up @@ -42,19 +45,35 @@ export function property(options: IPropertyDecoratorOptions = {}) {
// ConsoleWarnings.error("remove defaultValue from @property for class " + target.getType() + " property name is " + key);
// }
let defaultVal = null;
let returnValue = undefined;
let calcFunc = undefined;
if (!!options) {
returnValue = options.returnValue;
if (options.calcFunc) {
calcFunc = () => options.calcFunc(this);
}
if (typeof options.getDefaultValue === "function") {
defaultVal = options.getDefaultValue(this);
}
if (options.defaultValue !== undefined) {
defaultVal = options.defaultValue;
}
}
return this.getPropertyValue(key, defaultVal);
const res = this.getPropertyValue(key, defaultVal, calcFunc);
return returnValue !== undefined && res === undefined ? returnValue : res;
},
set: function (val: any) {
const newValue = processComputedUpdater(this, val);
let newValue = processComputedUpdater(this, val);
const prevValue = this.getPropertyValue(key);
if (!!options) {
if (options.isLowerCase) {
if (!newValue || typeof newValue !== "string") return;
newValue = newValue.toLowerCase();
}
if (!!options.onSetting) {
newValue = options.onSetting(newValue, this, prevValue);
}
}
if (newValue !== prevValue) {
this.setPropertyValue(key, newValue);
if (!!options && options.onSet) {
Expand Down
Loading