mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 07:53:39 +01:00
Get needed attribute working
Will cancel submit, shows validation message
This commit is contained in:
parent
ce84dd753a
commit
d9e95dae87
@ -10,7 +10,7 @@
|
||||
|
||||
|
||||
import {css, html} from "@lion/core";
|
||||
import {FormControlMixin} from "@lion/form-core";
|
||||
import {FormControlMixin, ValidateMixin} from "@lion/form-core";
|
||||
import 'lit-flatpickr';
|
||||
import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
|
||||
import {dateStyles} from "./DateStyles";
|
||||
@ -270,7 +270,7 @@ export function formatDateTime(date : Date, options = {dateFormat: "", timeForma
|
||||
return formatDate(date, options) + " " + formatTime(date, options);
|
||||
}
|
||||
|
||||
export class Et2Date extends Et2InputWidget(FormControlMixin(LitFlatpickr))
|
||||
export class Et2Date extends Et2InputWidget(FormControlMixin(ValidateMixin(LitFlatpickr)))
|
||||
{
|
||||
static get styles()
|
||||
{
|
||||
|
@ -1,7 +1,8 @@
|
||||
import {et2_IInput, et2_IInputNode} from "../et2_core_interfaces";
|
||||
import {et2_IInput, et2_IInputNode, et2_ISubmitListener} from "../et2_core_interfaces";
|
||||
import {Et2Widget} from "../Et2Widget/Et2Widget";
|
||||
import {dedupeMixin} from "@lion/core";
|
||||
import {ManualMessage} from "./ManualMessage";
|
||||
import {dedupeMixin, PropertyValues} from "@lion/core";
|
||||
import {ManualMessage} from "../Validators/ManualMessage";
|
||||
import {Required} from "../Validators/Required";
|
||||
|
||||
/**
|
||||
* This mixin will allow any LitElement to become an Et2InputWidget
|
||||
@ -37,7 +38,7 @@ export declare class Et2InputWidgetInterface
|
||||
|
||||
const Et2InputWidgetMixin = (superclass) =>
|
||||
{
|
||||
class Et2InputWidgetClass extends Et2Widget(superclass) implements et2_IInput, et2_IInputNode
|
||||
class Et2InputWidgetClass extends Et2Widget(superclass) implements et2_IInput, et2_IInputNode, et2_ISubmitListener
|
||||
{
|
||||
protected _oldValue : string | number | Object;
|
||||
protected node : HTMLElement;
|
||||
@ -66,6 +67,11 @@ const Et2InputWidgetMixin = (superclass) =>
|
||||
type: Boolean
|
||||
},
|
||||
|
||||
needed: {
|
||||
type: Boolean,
|
||||
reflect: true
|
||||
},
|
||||
|
||||
onchange: {
|
||||
type: Function
|
||||
},
|
||||
@ -83,6 +89,32 @@ const Et2InputWidgetMixin = (superclass) =>
|
||||
this.node = this.getInputNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* A property has changed, and we want to make adjustments to other things
|
||||
* based on that
|
||||
*
|
||||
* @param {import('@lion/core').PropertyValues } changedProperties
|
||||
*/
|
||||
updated(changedProperties : PropertyValues)
|
||||
{
|
||||
super.updated(changedProperties);
|
||||
|
||||
// Needed changed, add / remove validator
|
||||
if(changedProperties.has('needed'))
|
||||
{
|
||||
// Remove class
|
||||
this.classList.remove("et2_required")
|
||||
// Remove all existing Required validators (avoids duplicates)
|
||||
this.validators = (this.validators || []).filter((validator) => validator instanceof Required)
|
||||
this.setAttribute("required", this.needed);
|
||||
if(this.needed)
|
||||
{
|
||||
this.validators.push(new Required());
|
||||
this.classList.add("et2_required");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change handler calling custom handler set via onchange attribute
|
||||
*
|
||||
@ -169,12 +201,19 @@ const Et2InputWidgetMixin = (superclass) =>
|
||||
this._oldValue = this.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by etemplate2 to determine if we can submit or not
|
||||
*
|
||||
* @param messages
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isValid(messages)
|
||||
{
|
||||
var ok = true;
|
||||
debugger;
|
||||
|
||||
// Check for required
|
||||
if(this.options && this.options.needed && !this.options.readonly && !this.disabled &&
|
||||
if(this.needed && !this.readonly && !this.disabled &&
|
||||
(this.getValue() == null || this.getValue().valueOf() == ''))
|
||||
{
|
||||
messages.push(this.egw().lang('Field must not be empty !!!'));
|
||||
@ -215,6 +254,29 @@ const Et2InputWidgetMixin = (superclass) =>
|
||||
// it won't show up without validate()
|
||||
this.validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the template gets submitted. We return false if the widget
|
||||
* is not valid, which cancels the submission.
|
||||
*
|
||||
* @param _values contains the values which will be sent to the server.
|
||||
* Listeners may change these values before they get submitted.
|
||||
*/
|
||||
async submit(_values) : Promise<boolean>
|
||||
{
|
||||
this.submitted = true;
|
||||
|
||||
// If using Lion validators, run them now
|
||||
if(this.validate)
|
||||
{
|
||||
// Force update now
|
||||
this.validate(true);
|
||||
await this.validateComplete;
|
||||
|
||||
return (this.hasFeedbackFor || []).indexOf("error") == -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Et2InputWidgetClass;
|
||||
|
@ -1156,6 +1156,17 @@ export function loadWebComponent(_nodeName : string, _template_node, parent : Et
|
||||
return widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take attributes from a node in a .xet file and apply those to a WebComponent widget
|
||||
*
|
||||
* Any attributes provided that match a property (or attribute) on the widget will be adjusted according to
|
||||
* the passed arrayManager, coerced into the proper type, and set.
|
||||
* It is here that we find values or set attributes that should come from content.
|
||||
*
|
||||
* @param widget
|
||||
* @param {et2_arrayMgr} mgr
|
||||
* @param attributes
|
||||
*/
|
||||
function transformAttributes(widget, mgr : et2_arrayMgr, attributes)
|
||||
{
|
||||
|
||||
|
@ -2,8 +2,7 @@ import {ResultValidator} from "@lion/form-core";
|
||||
|
||||
/**
|
||||
* Manual validator for server-side validation messages passed
|
||||
* from Etemplate. It is always "activated", and just gives whatever
|
||||
* message is passed in when created.
|
||||
* from Etemplate. It just gives whatever message is passed in when created.
|
||||
*
|
||||
*/
|
||||
export class ManualMessage extends ResultValidator
|
14
api/js/etemplate/Validators/Required.ts
Normal file
14
api/js/etemplate/Validators/Required.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {Required as LionRequired} from "@lion/form-core";
|
||||
|
||||
export class Required extends LionRequired
|
||||
{
|
||||
/**
|
||||
* Give a message about this field being required. Could be customised according to MessageData.
|
||||
* @param {MessageData | undefined} data
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
static async getMessage(data)
|
||||
{
|
||||
return data.formControl.egw().lang("Field must not be empty !!!");
|
||||
}
|
||||
}
|
@ -158,7 +158,7 @@ export interface et2_ISubmitListener
|
||||
* @param _values contains the values which will be sent to the server.
|
||||
* Listeners may change these values before they get submitted.
|
||||
*/
|
||||
submit(_values) : void
|
||||
submit(_values) : boolean | Promise<boolean>
|
||||
}
|
||||
export const et2_ISubmitListener = "et2_ISubmitListener";
|
||||
et2_implements_registry.et2_ISubmitListener = function(obj : et2_widget)
|
||||
|
@ -905,9 +905,9 @@ export class etemplate2
|
||||
*
|
||||
* @param container
|
||||
* @param values
|
||||
* @return et2_widget|null first invalid widget or null, if all are valid
|
||||
* @return Promise<et2_widget>|Promise<Et2Widget>|null
|
||||
*/
|
||||
isInvalid(container : et2_container | undefined, values : object | undefined) : et2_widget | null
|
||||
async isInvalid(container : et2_container | undefined, values : object | undefined) : Promise<et2_ISubmitListener> | null
|
||||
{
|
||||
if(typeof container === 'undefined')
|
||||
{
|
||||
@ -917,19 +917,27 @@ export class etemplate2
|
||||
{
|
||||
values = this.getValues(container);
|
||||
}
|
||||
let invalid = null;
|
||||
let invalid = [];
|
||||
container.iterateOver(function(_widget)
|
||||
{
|
||||
if(_widget.submit(values) === false)
|
||||
let submit = _widget.submit(values);
|
||||
if(submit === false)
|
||||
{
|
||||
if(!invalid && !_widget.isValid([]))
|
||||
{
|
||||
invalid = _widget;
|
||||
invalid.push(_widget);
|
||||
}
|
||||
}
|
||||
else if(submit instanceof Promise)
|
||||
{
|
||||
invalid.push(submit.then(function(sub)
|
||||
{
|
||||
return sub ? false : this;
|
||||
}.bind(_widget)));
|
||||
}
|
||||
}, this, et2_ISubmitListener);
|
||||
|
||||
return invalid;
|
||||
return Promise.all(invalid);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -962,8 +970,27 @@ export class etemplate2
|
||||
{
|
||||
canSubmit = !(invalid = this.isInvalid(container, values));
|
||||
}
|
||||
invalid.then((widgets) =>
|
||||
{
|
||||
let invalid_widgets = widgets.filter((widget) => widget);
|
||||
|
||||
if(canSubmit)
|
||||
if(invalid_widgets.length)
|
||||
{
|
||||
// Show the first invalid widget, not the last
|
||||
if(invalid_widgets[0] && invalid_widgets[0] instanceof et2_widget)
|
||||
{
|
||||
let messages = [];
|
||||
let valid = invalid.isValid(messages);
|
||||
invalid.set_validation_error(messages);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
doSubmit();
|
||||
}
|
||||
});
|
||||
|
||||
let doSubmit = function()
|
||||
{
|
||||
if(typeof async == 'undefined' || typeof async == 'string')
|
||||
{
|
||||
@ -996,14 +1023,9 @@ export class etemplate2
|
||||
{
|
||||
this._widgetContainer.egw().debug("warn", "Missing menuaction for submit. Values: ", values);
|
||||
}
|
||||
}
|
||||
else if(invalid !== null)
|
||||
{
|
||||
// Show the first invalid widget, not the last
|
||||
let messages = [];
|
||||
let valid = invalid.isValid(messages);
|
||||
invalid.set_validation_error(messages);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
|
||||
return canSubmit;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user