I ran into a specific issue in a component after upgrading from 6.3 to 6.5.6. The component has after which 1 of 3 options is selected, and depending on which value is selected, another field should be displayed. At 6.3 there are no problems with this, after the upgrade to 6.5 the field is no longer displayed. All this in the component dialog box. The component has not changed. I noticed that the style has "hide" and it should disappear, but it doesn't. We have AEM version 6.5.6. I installed 6.5 myself and tested it and the component works. Then I installed service pack 6.5.6 and the component stopped working. This is a problem in the service pack. But I don’t understand why.
Incorrectly working component
Сorrectly working component
In this case, the javascript file is connected. There are no errors in the logs.
dialog
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Box"
sling:resourceType="cq/gui/components/authoring/dialog"
extraClientlibs="[app.site.campaign.email.box,app.site.campaign.email.dialog.paddingOptionsToggleable,app.site.campaign.email.dialog.scrollableTabs]">
<content
granite:class="cmp-box--editor"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<tabs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs">
<items jcr:primaryType="nt:unstructured">
<general
jcr:primaryType="nt:unstructured"
jcr:title="General"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<boxLayout
granite:class="cq-dialog-dropdown-showhide"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Box Layout"
name="./boxLayout"
text="Box Style">
<granite:data
jcr:primaryType="nt:unstructured"
cq-dialog-dropdown-showhide-tab=".list-option-listfrom-showhide-tab"
cq-dialog-dropdown-showhide-target=".boxlayout-list-option-listfrom-showhide-target"/>
<items jcr:primaryType="nt:unstructured">
<square
jcr:primaryType="nt:unstructured"
text="Square"
value="square"/>
<rectangle
jcr:primaryType="nt:unstructured"
text="Rectangle"
value="rectangle"/>
<flexibleHeight
jcr:primaryType="nt:unstructured"
text="Flex"
value="flex"/>
</items>
</boxLayout>
<hideOnView
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Hide Box"
name="./hideOnView">
<items jcr:primaryType="nt:unstructured">
<standard
jcr:primaryType="nt:unstructured"
text="Always visible"
value=""/>
<hideOnMobile
jcr:primaryType="nt:unstructured"
text="Hide on mobile"
value="mobile-hide"/>
<hideOnDesktop
jcr:primaryType="nt:unstructured"
text="Hide on desktop"
value="desktop-hide mobile-show"/>
</items>
</hideOnView>
<backgroundColor
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Background Color"
name="./backgroundColor">
<items jcr:primaryType="nt:unstructured">
<White
jcr:primaryType="nt:unstructured"
text="White"
value="#F8F8F8"/>
<Black
jcr:primaryType="nt:unstructured"
text="Black"
value="#191919"/>
<Transparent
jcr:primaryType="nt:unstructured"
text="Transparent"
value="#242424"/>
</items>
</backgroundColor>
<backgroundImage
granite:class="hide boxlayout-list-option-listfrom-showhide-target foundation-layout-util-vmargin"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<granite:data
jcr:primaryType="nt:unstructured"
showhidetargetclearfields="img:./backgroundImage"
showhidetargetvalue="square,rectangle"/>
<items jcr:primaryType="nt:unstructured">
<file
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/fileupload"
allowUpload="{Boolean}false"
autoStart="{Boolean}false"
class="cq-droptarget"
fieldLabel="Background Image"
fileNameParameter="./bgFileName"
fileReferenceParameter="./bgFileReference"
mimeTypes="[image/gif,image/jpeg,image/png]"
multiple="{Boolean}false"
name="./backgroundImage"
title="Background Image"
uploadUrl="${suffix.path}"
useHTML5="{Boolean}true"/>
</items>
</backgroundImage>
<boxLink
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
name="./boxLink"
required="false"
fieldLabel="Hyperlink"
rootPath="/content"/>
<boxLinkSuffix
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/inputgroup"
fieldLabel="Hyperlink suffix"
renderReadOnly="{Boolean}true">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Hyperlink suffix"
name="./boxLinkSuffix"/>
<rightButton
class="coral-Button--square"
icon="coral-Icon--adobeCampaign"
init="acmetadatapicker"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/button"
targetinput="input[name='./boxLinkSuffix']"/>
</boxLinkSuffix>
</items>
</column>
</items>
</general>
</items>
</tabs>
</items>
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs"
type="nav"/>
</content>
</jcr:root>
js
(function(document, $) {
'use strict';
// When dialog gets injected
$(document).on('foundation-contentloaded', function(e) {
$('.cmp-box--editor coral-select.cq-dialog-dropdown-showhide', e.target).each(function(i, element) {
// Show or hide touch UI Dialog components
var target = $(element).data('cqDialogDropdownShowhideTarget');
if (target) {
Coral.commons.ready(element, function(component) {
// If there is already an inital value make sure the according target element becomes visible
showHideTarget(component, target);
component.on('change', function() {
showHideTarget(component, target);
});
});
}
// Show or hide touch UI Dialog Tabs
var tab = $(element).data('cqDialogDropdownShowhideTab');
var displaySiteLogo = $(".cmp-box--editor coral-checkbox[name='./logo/displaySiteLogo']");
if (tab) {
Coral.commons.ready(element, function(component) {
// If there is already an inital value make sure the according tab element becomes visible
showHideTab(component, tab);
component.on('change', function() {
showHideTab(component, tab);
});
$(displaySiteLogo).change(function() {
showHideTab(component, tab);
});
});
}
});
$('.cmp-box--editor coral-Checkbox.cq-dialog-checkbox-showhide', e.target).each(function(i, element) {
// Show or hide touch UI Dialog components
var target = $(element).data('cqDialogDropdownShowhideTarget');
if (target) {
Coral.commons.ready(element, function(component) {
// If there is already an inital value make sure the according target element becomes visible
showHideTarget(component, target, $(component).attr("checked"));
component.on('change', function(chEve) {
showHideTarget(component, target, chEve.currentTarget.checked);
});
});
}
});
showHideTarget($('.cq-dialog-dropdown-showhide', e.target));
showHideTab($('.cq-dialog-dropdown-showhide', e.target));
});
/**
* Show or hide touch UI Dialog components based on the selection made in the dropdown/select.
*
* #param {component} component - currently selected element.
* #param {target} target - target elements.
*/
function showHideTarget(component, target, checkedVal) {
var value = component.value,
$component = $(component);
if ($component.hasClass("coral-Checkbox")) {
if (checkedVal)
value = $component.data("checkboxTarget");
}
$(target).each(function(i, targetObj) {
var targetValue = $(targetObj).data('showhidetargetvalue');
var array = targetValue.split(',');
$(targetObj).not('.hide').addClass('hide');
if ($.inArray(value, array) === -1) {
// Clear fields
var clearFields = $(targetObj).data('showhidetargetclearfields');
if (clearFields) {
showHideClearFields(clearFields);
}
} else {
$(targetObj).filter("[data-showhidetargetvalue='" + targetValue + "']").removeClass('hide');
}
});
}
/**
* Show or hide touch UI Dialog tabs based on the selection made in the dropdown/select.
*
* #param {component} component - Currently selected element.
* #param {tab} tab - Tab elements.
*/
function showHideTab(component, tab) {
var value = component.value;
$(tab).each(function(i, tabObj) {
var $tab = $(tabObj).parents('.coral-Panel');
var tabId = $tab.attr('aria-labelledby');
var tabHead = $('.cmp-box--editor coral-tabview').find('coral-tab#' + tabId);
var tabValue = $(tabObj).data('showhidetabvalue');
var showHideTabValueArray = tabValue.split(',');
$(tabHead).not('.hide').addClass('hide');
$(tabObj).not('.hide').addClass('hide');
// Check any target condition before show or hide tab
var showtab = true;
var customCondition = $(tabObj).data('customcondition');
if (customCondition) {
showtab = checkCustomCondition(value);
}
if ($.inArray(value, showHideTabValueArray) !== -1 && showtab) {
$(tabHead).removeClass('hide');
$(tabObj).filter("[data-showhidetabvalue='" + tabValue + "']").removeClass('hide');
} else {
// Clear fields
var clearFields = $(tabObj).data('showhidetabclearfields');
if (clearFields) {
showHideClearFields(clearFields);
}
}
});
}
/**
* Custom conditional checks.
*
* #param {string} value - Currently selected element.
* #returns {boolean} - Element condition true or false.
*/
function checkCustomCondition(value) {
var conditionResult = true;
var hideOverlayPosition;
var $chkDisplaySiteLogo = $(".cmp-box--editor coral-checkbox[name='./logo/displaySiteLogo']");
var $selBoxLayout = $(".cmp-box--editor input[name='./boxLayout']");
var $selLogoPosition = $(".cmp-box--editor input[name='./logo/position']");
switch (value) {
case 'square':
hideOverlayPosition = $chkDisplaySiteLogo.is('[checked]') && $selLogoPosition.attr('value') === 'leftMiddle';
if (hideOverlayPosition) {
showHideOverlaySelection(true);
} else {
showHideOverlaySelection(false);
}
conditionResult = !$chkDisplaySiteLogo.is('[checked]') || hideOverlayPosition;
break;
case 'leftMiddle':
hideOverlayPosition = $selBoxLayout.attr('value') === 'square' && $chkDisplaySiteeLogo.is('[checked]');
showHideOverlaySelection(hideOverlayPosition);
conditionResult = !$chkDisplaySiteLogo.is('[checked]') || hideOverlayPosition;
break;
case 'topLeft':
case 'topCenter':
case 'topRight':
showHideOverlaySelection(false);
conditionResult = $selBoxLayout.attr('value') === 'square' && !$chkDisplaySiteLogo.is('[checked]');
break;
}
return conditionResult;
}
/**
* Hide/Un-hide overlay position selection elements.
*
* #param {boolean} hide - Hide or un-hide.
*/
function showHideOverlaySelection(hide) {
var $overlayPositionSelection = $(".cmp-box--editor coral-select[name='./overlay/overlayPosition']");
if (hide) {
var $hiddenInput = $overlayPositionSelection.find('input');
$overlayPositionSelection
.find('coral-selectlist-item')
.filter('[value!="bottomRight"]')
.not('.hide')
.addClass('hide');
$hiddenInput
.attr('name', './overlay/overlayPosition')
.attr('value', 'bottomRight');
$overlayPositionSelection.find('span.coral3-Select-label').text('Bottom Right');
} else {
$overlayPositionSelection.find('coral-selectlist-item').removeClass('hide');
}
}
/**
* Clear touch UI Dialog fields based on the selection made in the dropdown/select.
*
* #param {Array} clearFields - Array of field type and field names in format {<fieldType>:<fieldName>}.
* Fields supported: checkbox, textfield, image (fileupload).
*/
function showHideClearFields(clearFields) {
var fieldsArray = [];
if (clearFields.indexOf(',') === -1) {
fieldsArray.push(clearFields);
} else {
fieldsArray = clearFields.split(',');
}
fieldsArray.forEach(function(field) {
if (field.indexOf(':') !== -1) {
var delimiter = field.lastIndexOf(':');
var inputType = field.substring(0, delimiter);
var inputName = field.substring(delimiter + 1);
if (inputType === 'checkbox') {
clearCheckBox(inputName);
} else if (inputType === 'textfield') {
clearTextField(inputName);
} else if (inputType === 'img') {
clearImage(inputName);
}
}
});
}
/**
* Uncheck checkbox.
*
* #param {string} name - Checkbox input name.
*/
function clearCheckBox(name) {
$(".cmp-box--editor coral-checkbox[name='" + name + "']").removeAttr('checked');
}
/**
* Reset textfield to empty.
*
* #param {string} name - Textfield input name.
*/
function clearTextField(name) {
$(".cmp-box--editor input[name='" + name + "']").attr('value', '');
}
/**
* Delete fileupload image.
*
* #param {string} name - Image input name.
*/
function clearImage(name) {
var $imgInput = $(".cmp-box--editor input[name='" + name + "']"),
$imgInputParent = $imgInput.parents('.coral-FileUpload--dropSupport').parent(),
$imgFileName = $imgInputParent.find('input.cq-FileUpload-filename'),
$imgFileReference = $imgInputParent.find('input.cq-FileUpload-filereference'),
$imgFileDelete = $imgInputParent.find('input.cq-FileUpload-filedelete');
$imgInput.attr('value', '');
$imgInputParent.find('.cq-FileUpload-thumbnail-img').remove();
if ($imgFileName.length > 0) {
$imgFileName.attr('value', '');
$imgFileName.removeAttr('disabled');
}
if ($imgFileReference.length > 0) {
$imgFileReference.attr('value', '');
$imgFileReference.removeAttr('disabled');
}
if ($imgFileDelete.length > 0) {
$imgFileDelete.attr('value', 'true');
$imgFileDelete.removeAttr('disabled');
}
}
}(document, Granite.$));
Thanks a lot!
Related
In react-leaflet v4, the Popup component has a default href associated with the close button that directs to #close. Is there a way in React to modify this href or disable the href redirection? It's breaking my react-dom HashRouter.
Of note, Popup.js in Leaflet 1.8 has the following code:
var closeButton = this._closeButton = DomUtil.create('a', prefix + '-close-button', container);
closeButton.setAttribute('role', 'button'); // overrides the implicit role=link of <a> elements #7399
closeButton.setAttribute('aria-label', 'Close popup');
closeButton.href = '#close';
closeButton.innerHTML = '<span aria-hidden="true">×</span>';
The same issue is also in angular - means it seems to be the leaflet Lib:
// leaflet.js
close: function () {
if (this._map) {
this._map.removeLayer(this);
}
return this;
},
The close function has not even the $event as an argument and the "default" isn't prevented. This leaves us only dirty hacks:
Get the close button after the marker was displayed
Add a click handler more
Add a prefentDefault
yourMethodOpensTheToolTip(marker: Marker) {
if (marker && marker.openPopup) {
marker.openPopup();
// 1. get the close buttons, after the opened the popup
const closeButtons = document.getElementsByClassName('leaflet-popup-close-button');
// 2. add the event handler - if you have more than one, loop here
if (closeButtons && closeButtons.length > 0) {
L.DomEvent.on(closeButtons[0] as HTMLElement, 'click', function(ev){
ev.preventDefault(); // 3. stop it here
});
}
Just for reference the #close button as HTML:
Try something like this. It will probably disable any other hrefs that you may have in the popup though.
document.querySelector('.leaflet-pane.leaflet-popup-pane')!.addEventListener('click', event => {
event.preventDefault();
});
You can utilize useRef hooks and create a click event in the marker
const mapRef = useRef(null);
// event listener to handle marker click
const handleClick = () => {
mapRef.current._popup._closeButton.addEventListener('click', (event) => {
event.preventDefault();
})
};
const map = (<MapContainer center={position} zoom={13} scrollWheelZoom={false} style={{ height: '350px', width: '100%' }} ref={mapRef}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker
position={position}
eventHandlers={{
click: (e) => handleClick(),
}}
>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</MapContainer>)
if you are using GeoJSON you can use onEachFeature props
const onEachCountry = (country, layer) => {
const countryName = country.properties.ADMIN;
layer.on('click', function (e) {
layer
.bindPopup(countryName)
.openPopup()
._popup._closeButton.addEventListener('click', (event) => {
event.preventDefault();
});
});
};
const map = (<MapContainer style={{ height: '300px' }} zoom={1} center={[20, 100]}>
<GeoJSON style={countryStyle} data={mapData.features} onEachFeature={onEachCountry} />
</MapContainer>)
In my React project with react-leaflet v4, I had the same issue and I solved it with the "popupopen" event :
https://leafletjs.com/reference.html#marker-popupopen
<Marker
position={position}
eventHandlers={{
popupopen: (e) => {
e.popup._closeButton.removeAttribute("href");
e.popup._closeButton.style.cursor = "pointer";
}
}}
>
<Popup>
<p>Lorem ipsum dolor sit amet</p>
</Popup>
</Marker>
I hope it will help.
Building on Paul's answer. Here is the solution if you have multiple popups. This will handle the close button click event on all the popups that are open on the leaflet map.
// This is a stopgap till Leaflet fixes its issue with close buttons in popups in Leaflet maps
let popupCloseButtonsHTMLCollection = document.getElementsByClassName('leaflet-popup-close-button');
if(popupCloseButtonsHTMLCollection && popupCloseButtonsHTMLCollection.length > 0){
//convert the popupCloseButtonsHTMLCollection to array
var popupArray = [].slice.call(popupCloseButtonsHTMLCollection);
popupArray.forEach(button =>{
L.DomEvent.on(button as HTMLElement, 'click', function(ev){
ev.preventDefault();
});
});
}
When I add a SimplePlanningCalendar to my app, I got the following Error.
I added the calendar with a minimal configuration to my app.
<IconTabBar xmlns="sap.m"
id="idCategoryMenu"
selectedKey="Home"
headerMode="Inline"
stretchContentHeight="true"
applyContentPadding="false"
select=".onSelectCategory"
items="{
path: 'backend>/CategorySet',
parameters: {
expand: 'Reports'
},
sorter: {
path: 'Sort'
},
templateShareable: true
}">
<items>
<IconTabFilter id="myIconTabFilter" key="{backend>Uuid}" text="{backend>Name}">
<!-- ... -->
<SinglePlanningCalendar>
<appointments>
<unified:CalendarAppointment xmlns:unified="sap.ui.unified"
title="{title}"
startDate="{startDate}"
endDate="{endDate}"
/>
</appointments>
</SinglePlanningCalendar>
<!-- ... -->
</IconTabFilter>
</items>
</IconTabBar>
When I debug the app, I come to the following line inside the SinglePlanningCalendar.js where a key from the given vView parameter is requested, but the parameter only holds a string.
Anyone else had this problem before and knows why or how to solve this?
The problem is caused by the control implementation itself in the current version (1.71.21) I use for my development.
The fix in the commit 45696fe is available as of UI5 1.75.x.
Since I cannot change my version, I implemented the given solution in my package:
{ // Controller
onInit: function () {
// ...
this.calendarTemporaryFix(); // Not needed since UI5 1.75
},
calendarTemporaryFix: function () {
// SinglePlanningCalendar required from "sap/m/SinglePlanningCalendar"
const fnSetSelectedView = SinglePlanningCalendar.prototype.setSelectedView;
SinglePlanningCalendar.prototype.setSelectedView = function (vView) {
if (typeof vView === "string") {
vView = sap.ui.getCore().byId(vView);
}
return fnSetSelectedView.call(this, vView);
};
},
// ...
}
I need to highlight a few of the table's cell border colors on the basis of a condition and pre-fill it with some negative value. Then I need to SAVE/POST this value to proceed further.
View.xml
<t:Column width="100px">
<Label text="ActualQty"/>
<t:template>
<Input id="idInput" value="{ parts: [ {path: 'viewData>ACT_QTY'}, {path: 'viewData>MTART'} ], formatter: '._formatter.defaultInput' }">
<customData>
<core:CustomData key="colorclass" value="{path: 'viewData>MTART', formatter: '._formatter.formatCell'}" writeToDom="true"/>
</customData>
</Input>
</t:template>
</t:Column>
Formatter.js
formatCell: function (iValue) {
try {
iValue.toString();
} catch (err) {
iValue = "foo";
}
return iValue.toString();
},
defaultInput: function (iValue, iValue1) {
if (iValue !== 0 && iValue1 === "HALB") {
iValue = "-1";
return iValue;
} else {
return iValue;
}
}
style.css
div[data-colorclass="HALB"] {
border: 4px solid #fdf6b1 !important;
}
Highlighting and the default value is appearing. But inside the controller, the input value is not coming.
If I remove parts and pass single input param to formatter function, it's working. But I need both the values to built my logic.
Update
Now I am using Composite Binding to make the binding as Two-way.
View.xml
<Input id="idInput" value="{ parts: [ {path: 'viewData>ACT_QTY'}, {path: 'viewData>MTART'} ], type: '._Compound', formatter: '._formatter.defaultInput' }">
Compound.js
sap.ui.define([
"sap/ui/model/CompositeType",
"dismantling/bom/integration/model/type/Compound"
], CompositeType => CompositeType.extend('Compound', {
constructor: function () {
CompositeType.apply(this, arguments);
this.bParseWithValues = true; // make 'parts' available in parseValue
},
formatValue: iValue => iValue,
parseValue: bValue => bValue,
validateValue: vValue => { /*validate...*/ },
}));
In the controller file, I am passing Compound type as _Compound. I am not getting any errors in the console.
Still, I am not able to get the formatter passed value inside the controller.
Your formatter is correct. Make sure sure that the values are actually accessible under your binding path and that the formatter is accessible to the view. If both these things are ensured, your function will work just fine.
I have a problem to display data in my detail page. I've tried almost everything but its dosnt work. On main page everything looks fine. Routing work (display proper ID on network address).
Details.controller.js :
return Controller.extend("sapProject.controller.Details", {
onInit: function () {
var oTable = this.getView().byId("details");
var oModel = new sap.ui.model.json.JSONModel();
oModel.loadData("model/Object.json");
oTable.setModel(oModel);
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.getRoute("Details").attachMatched(this._onRouteMatched, this);
},
_onRouteMatched : function (oEvent) {
var oArgs, oView;
oArgs = oEvent.getParameter("arguments");
oView = this.getView();
oView.bindElement({
path : "/Objects(" + oArgs.employeeId + ")",
events : {
dataRequested: function () {
oView.setBusy(true);
},
dataReceived: function () {
oView.setBusy(false);
}
}
});
},
and this is my Details.view.xml:
<Page
id="details"
title="{i18n>EmployeeDetailsOf} {FirstName} {LastName}"
showNavButton="true"
navButtonPress="onBack"
class="sapUiResponsiveContentPadding">
<content>
<Panel
width="auto"
class="sapUiResponsiveMargin sapUiNoContentPadding">
<headerToolbar >
<Toolbar>
<Title text="{i18n>EmployeeIDColon} {EmployeeID}" level="H2"/>
<ToolbarSpacer />
</Toolbar>
</headerToolbar>
<content>
<f:SimpleForm>
<f:content>
<Label text="{i18n>FirstName}" />
<Text text="{FirstName}" />
<Label text="{i18n>LastName}" />
</f:content>
</f:SimpleForm>
</content>
</Panel>
</content>
</Page>
I think you are binding an empty model to your detail view because probably the loadData function is not completed when you set the model on the Table.
Try to load your json file in the manifest (best option) or differ the setModel on the _onRouteMatched function (although I don't see any table in your detail view).
EDIT:
You can also use this code after oModel.loadData("model/Object.json");
oModel.attachEventOnce("requestCompleted", function(oEvent) {
// Here your file is fully loaded
});
Firstly I recommend you to bind like this:
var sObjectPath = this.getModel().createKey("Objects", {
ID: oArgs.employeeId
});
this._bindView("/" + sObjectPath);
...
}
_bindView: function (sObjectPath) {
//Todo: Set busy indicator during view binding
this.getView().bindElement({
path: sObjectPath,
parameters: {
},
events: {
change: this._onBindingChange.bind(this),
dataRequested: function () {
}.bind(this),
dataReceived: function () {
}.bind(this)
}
});
},
Secondly check if oArgs.employeeId has a valid value and also if the model is loaded with data, easily set a brekapoint or write console.log(this.getView().getModel().oData).
I try to use the template:if for my XML View.
As an example i have this:
<mvc:View controllerName="Test_Start.controller.View"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:mvc="sap.ui.core.mvc"
xmlns:temp="http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1"
displayBlock="true" xmlns="sap.m">
<App>
<pages>
<Page title="{i18n>title}">
<content>
<temp:if test="{= ${Data>Enable1} === 'X'}">
<Text text="Hallo"/>
</temp:if>
</content>
</Page>
</pages>
</App>
</mvc:View>
and my Component.js looks like this:
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"Test_Start/model/models",
"sap/ui/model/odata/v2/ODataModel",
"sap/ui/core/util/XMLPreprocessor"
], function(UIComponent, Device, models, ODataModel, XMLPreprocessor) {
"use strict";
return UIComponent.extend("Test_Start.Component", {
metadata: {
manifest: "json"
},
/**
* The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
* #public
* #override
*/
init: function() {
// call the base component's init function
UIComponent.prototype.init.apply(this, arguments);
// set the device model
this.setModel(models.createDeviceModel(), "device");
},
onBeforeRendering: function(){
var oModel = new ODataModel("/sap/opu/odata/SAP/ZPFO_CKPT_ODATA_DYN_SRV/"),
oMetaModel = oModel.getMetaModel(),
sPath = "/DataSet";
oMetaModel.loaded().then(function() {
var oTemplateView = sap.ui.view({
preprocessors: {
xml: {
bindingContexts : {
meta : oMetaModel.getMetaContext(sPath)
},
models: {
meta: oMetaModel
}
}
},
type : sap.ui.core.mvc.ViewType.XML,
viewName: "Test_Start.view.View"
});
oTemplateView.setModel(oModel);
oTemplateView.bindElement(sPath);
});
}
});
});
Now, when I try to run my App, i get the following error:
XMLTemplateProcessor-dbg.js:53 Uncaught Error: failed to load
'http://schemas/sap/com/sapui5/extension/sap/ui/core/template/1/if.js'
from
../../resources/http://schemas/sap/com/sapui5/extension/sap/ui/core/template/1/if.js:
404 - Not Found
I did some research and found out, that i probably load the preprocessor at the wrong time, but I seem to can't find the right place to load it.
I use this SAPUI5 SDK example for my work.
Edit
I found a solution for my problem:
instead of an "onBeforeRendering" function, now i'm using a "createContent" function. Also i deleted the "init" completly.
In adition to that, I implemented an oViewContainer, like it is used in the sample.
Also controller name "Test_Start.Component" doesn't match the controllerName attribute in the view "Test_Start.controller.View".