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

🐛 Handle field with default expression withot dependencies #696

Merged
merged 3 commits into from
Jan 21, 2025
Merged
Changes from all commits
Commits
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
133 changes: 51 additions & 82 deletions src/app/gui/form/formservice.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function FormService() {
addActionsForForm(actions) {},

postRender(element) {
// hook for listener to chenge DOM
// hook for listener to change DOM
}

};
Expand Down Expand Up @@ -108,7 +108,7 @@ function FormService() {

/**
* Force update state of the service
* (e.g., setted on a child to parent form service relation)
* (e.g., set on a child to parent form service relation)
*/
this.state = {
layerid: layer.getId(),
Expand Down Expand Up @@ -148,14 +148,7 @@ function FormService() {
* @since 3.8.0
*/
this.default_expression_fields_on_update = [];

/**
* Wheter to listen for changes when `saveDefaultExpressionFieldsNotDependencies` is called
*
* @since 3.8.0
*/
this.listenChangeInput = true;


this.setFormFields(fields);

if (this.layer && options.formStructure) {
Expand All @@ -176,17 +169,22 @@ proto.setReady = function(bool = false) {

/**
* Called when an input change value
*
*
* @param input
*/
proto.changeInput = function(input) {
this.feature.set(input.name, input.value);
if (true === this.listenChangeInput) {
this.evaluateFilterExpressionFields(input);
this.evaluateDefaultExpressionFields(input);
proto.changeInput = async function(input) {
try {
//need to set property
this.feature.set(input.name, input.value);
await this.evaluateFilterExpressionFields(input);
await this.evaluateDefaultExpressionFields(input);
this.isValid(input);
this.isUpdated(input);
} catch(e) {
console.warn(e);
}
//emit event changeInput
this.emit('changeInput', input);
};

/**
Expand Down Expand Up @@ -222,39 +220,41 @@ proto.setUpdate = function(bool = false, options = {}) {
* Evaluate filter expression
*
* @param input
* @return Promise
*/
proto.evaluateDefaultExpressionFields = function(input = {}) {
const filter = this.default_expression_fields_dependencies[input.name];
if (filter) {
filter.forEach(dependency_field => {
return Promise.allSettled(filter.forEach(dependency_field =>
FormService._getDefaultExpression({
parentData: this.parentData,
qgs_layer_id: this.layer.getId(),
field: this._getField(dependency_field),
feature: this.feature,
})
})
))
}
};

/**
* Evaluate filter expression fields
*
* @param input
* @return Promise
*/
proto.evaluateFilterExpressionFields = function(input = {}) {
const filter = this.filter_expression_fields_dependencies[input.name];
if (filter) {
// on form service inititalization `filter_expression` option has
// `referencing_fields` or `referenced_columns` from another layer
filter.forEach(dependency_field => {
return Promise.allSettled(filter.forEach(dependency_field =>
FormService._getFilterExpression({
parentData: this.parentData,
qgs_layer_id: this.layer.getId(),
field: this._getField(dependency_field),
feature: this.feature,
})
})
))
}
};

Expand Down Expand Up @@ -579,73 +579,42 @@ proto.clearAll = function() {
proto.saveDefaultExpressionFieldsNotDependencies = async function() {
if (0 === this.default_expression_fields_on_update.length) { return }

// disable listen changeInput
this.listenChangeInput = false;
// Array contains field name already resolved with server default_expression request
const requested_expressions = [];
// array of defaultExpressionPromises request
const pending_expressions = [];

// loop through default_expression_fields
for (let i = 0; i < this.default_expression_fields_on_update.length; i++) {

// extract all dependency fields of current field
const dFs = Object.keys(this.default_expression_fields_dependencies)
.filter(field => {
return (
// check if dependency field is field on update
this.default_expression_fields_on_update.find(({name}) => name === field) &&
// if it has bind current field
this.default_expression_fields_dependencies[field].find(fieldName => fieldName === this.default_expression_fields_on_update[i].name)
)
});

// id current field has a Array (at least one) dependency fields
// need to evaluate its value and after evaluate field value expression
for (let i = 0; i < dFs.length; i++) {
// in case already done a default_expression request evaluation from server
if (undefined !== requested_expressions.find(name => dFs[i] === name)) {
continue;
}
// get value. Need to wait response
try {
const value = await FormService._getDefaultExpression({
field: this._getField(dFs[i]),
feature: this.feature,
qgs_layer_id: this.layer.getId(),
parentData: this.parentData
});
// update field with evaluated value to feature
this.feature.set(dFs[i], value);
// add to array
requested_expressions.push(dFs[i]);
} catch(e) {
console.warn(e);
}
}

}

this.default_expression_fields_on_update.forEach(field => {
if (undefined === requested_expressions.find(name => field.name === name)) {
pending_expressions.push(FormService._getDefaultExpression({
field,
feature: this.feature,
qgs_layer_id: this.layer.getId(),
parentData: this.parentData
}))
}
});

try {
await Promise.allSettled(pending_expressions);
//@since 3.11.0 get unique field names that has dependencies from another fields
const fields_with_dependencies = new Set(Object.values(this.default_expression_fields_dependencies).flat());
//get all fields with default expression without dependencies
const fields_without_dependencies = this.default_expression_fields_on_update
.filter(({ name }) => !fields_with_dependencies.has(name))
//set property value of field by default expression result from server
await Promise.allSettled(fields_without_dependencies
.map(field => new Promise(async (resolve, reject) => {
try {
//get current value of field
const cvalue = field.value;
//get value after calculate default expression from server
const value = await FormService._getDefaultExpression({
field,
feature: this.feature,
qgs_layer_id: this.layer.getId(),
parentData: this.parentData
});
//check if changed
if (cvalue !== value) {
//wait until changeInput method is resolved
await new Promise((resolve) => this.once('changeInput', resolve))
}
resolve();
} catch(e) {
console.warn(e);
reject();
}
})
)
)
} catch(e) {
console.warn(e);
}

// enable listen changeInput
this.listenChangeInput = true;

};

/**
Expand Down
Loading