Skip to content

Commit

Permalink
Perform field constraint validation immediately when updating fields/…
Browse files Browse the repository at this point in the history
…loading feature
  • Loading branch information
manisandro committed Jul 1, 2024
1 parent 1b246a2 commit 0302cd9
Showing 1 changed file with 25 additions and 11 deletions.
36 changes: 25 additions & 11 deletions components/AttributeForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ class AttributeForm extends React.Component {
formValid: true,
captchaResponse: null
};
constructor(props) {
super(props);
this.form = null;
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.editContext.changed !== this.props.editContext.changed) {
this.props.setCurrentTaskBlocked(this.props.editContext.changed === true, LocaleUtils.tr("editing.unsavedchanged"));
Expand All @@ -79,6 +83,8 @@ class AttributeForm extends React.Component {
this.loadRelationValues(this.props.editContext.feature, (newFeature) => {
this.props.setEditContext(this.props.editContext.id, {feature: newFeature});
});
// Re-validate feature field constraints
this.validateFieldConstraints(this.props.editContext.feature);
}
}
editLayerId = (layerId) => {
Expand Down Expand Up @@ -173,6 +179,7 @@ class AttributeForm extends React.Component {
const newProperties = {...this.props.editContext.feature.properties, [key]: value};
const newFeature = {...this.props.editContext.feature, properties: newProperties};
this.props.setEditContext(this.props.editContext.id, {feature: newFeature, changed: true});
this.validateFieldConstraints(newFeature);
};
editMapPrefix = () => {
return (this.props.editConfig.editDataset.match(/^[^.]+\./) || [""])[0];
Expand Down Expand Up @@ -328,6 +335,8 @@ class AttributeForm extends React.Component {
this.loadRelationValues(feature, (newFeature) => {
this.props.setEditContext(this.props.editContext.id, {feature: newFeature, changed: false});
});
// Re-validate feature field constraints
this.validateFieldConstraints(feature);
} else {
this.props.setEditContext(this.props.editContext.id, {feature: feature, changed: false});
}
Expand All @@ -346,6 +355,7 @@ class AttributeForm extends React.Component {
}
};
setupChangedObserver = (form) => {
this.form = form;
if (form) {
form.observer = new MutationObserver(() => {
this.setState({formValid: form.checkValidity()});
Expand All @@ -363,11 +373,7 @@ class AttributeForm extends React.Component {
this.props.setEditContext(this.props.editContext.id, {changed: true});
}
};
onSubmit = (ev) => {
ev.preventDefault();
const form = ev.target;

// Constraint validation
validateFieldConstraints = (feature, validCallback = null) => {
const constraintExpressions = this.props.editConfig.fields.reduce((res, cur) => {
if (cur.constraints?.expression) {
return {
Expand All @@ -377,23 +383,29 @@ class AttributeForm extends React.Component {
}
return res;
}, {});
parseExpressionsAsync(constraintExpressions, this.props.editContext.feature, this.props.iface, this.editMapPrefix(), this.props.map.projection, false).then(result => {
parseExpressionsAsync(constraintExpressions, feature, this.props.iface, this.editMapPrefix(), this.props.map.projection, false).then(result => {
let valid = true;
Object.entries(result).forEach(([key, value]) => {
if (value === false) {
valid &= (value === true);
const element = form.elements.namedItem(key);
const element = this.form.elements.namedItem(key);
element.setCustomValidity(this.props.editConfig.fields.find(field => field.id === key)?.constraints?.placeholder ?? LocaleUtils.tr("editing.contraintviolation"));
}
});
if (!valid) {
this.setState({formValid: false});
} else {
this.doSubmit(form);
if (validCallback) {
validCallback();
}
}
});
};
doSubmit = (form) => {
onSubmit = (ev) => {
ev.preventDefault();
this.validateFieldConstraints(this.props.editContext.feature, this.doSubmit);
};
doSubmit = () => {

this.setState({busy: true});

Expand All @@ -419,10 +431,10 @@ class AttributeForm extends React.Component {
const featureUploads = {};

// Collect all values from form fields
const fieldnames = Array.from(form.elements).map(element => element.name).filter(x => x && x !== "g-recaptcha-response");
const fieldnames = Array.from(this.form.elements).map(element => element.name).filter(x => x && x !== "g-recaptcha-response");
fieldnames.forEach(name => {
const fieldConfig = (curConfig.fields || []).find(field => field.id === name) || {};
const element = form.elements.namedItem(name);
const element = this.form.elements.namedItem(name);
if (element) {
const parts = name.split("__");
let value = element.type === "radio" || element.type === "checkbox" ? element.checked : element.value;
Expand Down Expand Up @@ -576,6 +588,8 @@ class AttributeForm extends React.Component {
this.loadRelationValues(result, (newFeature) => {
this.props.setEditContext(this.props.editContext.id, {action: 'Pick', feature: newFeature, changed: false});
});
// Re-validate feature field constraints
this.validateFieldConstraints(result);
} else {
this.props.setEditContext(this.props.editContext.id, {action: 'Pick', feature: result, changed: false});
}
Expand Down

0 comments on commit 0302cd9

Please sign in to comment.