diff --git a/modules/templates/global-elements.xml b/modules/templates/global-elements.xml
index 4dfa08f7f7..0c04fd9b9f 100644
--- a/modules/templates/global-elements.xml
+++ b/modules/templates/global-elements.xml
@@ -338,6 +338,12 @@
// Match all affected elements and get date div value
$(target).find('.date').each(function(_idx, dateEl){
var dateValue = $(dateEl).data('date');
+
+ if (String(dateValue).length === 0 || !dateValue) {
+ $(dateEl).html('');
+ return;
+ }
+
var globalDate = moment(dateValue);
// Check for lang config
diff --git a/ui/src/layout-editor/viewer.js b/ui/src/layout-editor/viewer.js
index 80e684fa45..5fd01aaea2 100644
--- a/ui/src/layout-editor/viewer.js
+++ b/ui/src/layout-editor/viewer.js
@@ -1783,6 +1783,14 @@ Viewer.prototype.renderElementContent = function(
}
}
+ if (extendOverrideKey !== null || extendWithDataKey !== null) {
+ // Validate element data
+ self.validateElementData(
+ element,
+ convertedProperties[extendOverrideKey],
+ );
+ }
+
// Escape HTML
convertedProperties.escapeHtml = template?.extends?.escapeHtml;
@@ -1950,6 +1958,82 @@ Viewer.prototype.validateElement = function(
}
};
+/**
+ * Validate element data
+ * @param {Object} element
+ * @param {String} data
+ */
+Viewer.prototype.validateElementData = function(
+ element,
+ data,
+) {
+ const $elementContainer =
+ this.DOMObject.find(`#${element.elementId}`);
+
+ // Get error message
+ let $messageContainer = $elementContainer.find('.empty-element-data');
+ if ($messageContainer.length === 0) {
+ $messageContainer = $(
+ `
+
+
`);
+
+ $messageContainer.appendTo($elementContainer);
+ }
+
+ const isNotValid = !data || typeof data === 'undefined' || data === '';
+
+ if (isNotValid) {
+ const errorArray = [];
+ const hasGroup = Boolean(element.groupId);
+ const $groupContainer = (hasGroup) ?
+ $elementContainer.parents('.designer-element-group') : null;
+ const elementType = element.elementType;
+
+ // Add if elemens has no group or
+ // if has group but the group doesn't have message yet
+ if (
+ !hasGroup ||
+ (
+ hasGroup &&
+ $groupContainer.find('> .empty-element-data').length === 0
+ )
+ ) {
+ errorArray.push(
+ '' +
+ elementType.charAt(0).toUpperCase() +
+ elementType.substring(1) +
+ ' element' +
+ '
');
+
+ errorArray.push(
+ '' +
+ layoutEditorTrans.emptyElementData +
+ '
');
+ // If element has group, move error to group
+ (hasGroup) && $messageContainer.appendTo(
+ $elementContainer.parents('.designer-element-group'),
+ );
+
+ // Set title/tooltip
+ $messageContainer.tooltip('dispose')
+ .prop('title', '' +
+ errorArray.join('') + '
');
+ $messageContainer.tooltip();
+
+ // Show tooltip
+ $messageContainer.removeClass('d-none');
+ }
+
+ // Remove message from element if it's in a group
+ if (hasGroup) {
+ $elementContainer.find('.empty-element-data').remove();
+ }
+ } else {
+ $messageContainer.remove();
+ }
+};
+
/**
* Play preview
* @param {string} url - Preview url
diff --git a/ui/src/style/layout-editor.scss b/ui/src/style/layout-editor.scss
index 07b0e822b6..41892c2932 100644
--- a/ui/src/style/layout-editor.scss
+++ b/ui/src/style/layout-editor.scss
@@ -1243,7 +1243,7 @@ body.editor-opened {
opacity: 0.3;
}
- & > .invalid-parent {
+ & > .invalid-parent, & > .empty-element-data {
z-index: $viewer-object-group-bts-z-index !important;
}
@@ -1271,7 +1271,7 @@ body.editor-opened {
}
.designer-element, .designer-element-group {
- .invalid-parent {
+ .invalid-parent, .empty-element-data {
position: absolute;
padding: 2px 5px;
border-radius: 4px;
@@ -1286,8 +1286,10 @@ body.editor-opened {
opacity: 0.6;
}
- &:hover .invalid-parent {
- opacity: 0.8;
+ &:hover {
+ .invalid-parent, .empty-element-data {
+ opacity: 0.8;
+ }
}
}
diff --git a/views/layout-designer-page.twig b/views/layout-designer-page.twig
index 255fb76c7c..3b2f8b108f 100644
--- a/views/layout-designer-page.twig
+++ b/views/layout-designer-page.twig
@@ -78,6 +78,7 @@
actions: "{% trans "Actions" %}",
welcomeModalMessage: "{% trans "This is published and cannot be edited. You can checkout for editing below, or continue to view it in a read only mode." %}",
showingSampleData: "{% trans "Showing sample data" %}",
+ emptyElementData: "{% trans "Has empty data" %}",
};
var viewerTrans = {