Why UI5 controls rendered inside a custom control are not rerendered on property change? - sapui5

I have created a custom control my.Control that renders a sap.m.Text directly and receives another one by an aggregation.
Paste an example in one file for simplicity:
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>SAPUI5 example</title>
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_belize"
data-sap-ui-libs="sap.m, sap.ui.core"
data-sap-ui-compatVersion="edge"
data-sap-ui-async="true">
</script>
<script>
sap.ui.getCore().attachInit(function () {
sap.ui.core.Control.extend("my.Control", {
metadata: {
aggregations: {
testControl: {
type: 'sap.m.Text',
multiple: false,
singularName: 'testControl'
}
}
},
renderer: function (oRm, oControl) {
oRm.openStart('div', oControl);
oRm.openEnd();
oRm.text('DIRECTLY GENERATED CONTROL : ');
oRm.renderControl(new sap.m.Text('direct-control', {text: 'initial value'}));
oRm.openStart('br');
oRm.openEnd();
oRm.text('AGGREGATION PASSED CONTROL : ');
oRm.renderControl(oControl.getTestControl());
oRm.close('div');
}
});
new my.Control({
testControl: [
new sap.m.Text('passed-control', {text: 'initial value'})
]
}).placeAt('content');
});
</script>
</head>
<body class="sapuiBody" id="content">
</body>
</html>
Both load OK. But when editing its text property via Javascript the passed control is updated and the other one is not:
sap.ui.getCore().byId('passed-control').setText('edited value')
Control is rerendered
sap.ui.getCore().byId('direct-control').setText('edited value')
Control is not rerendered
If I execute sap.ui.getCore().byId('direct-control').rerender() then "direct-control" is rerendered with "edited value" as text.
Why do they behave differently?
Is there a way to configure this behaviour?
Thanks.

Related

Image not displaying in SAP UI5 Webpage

I am new to SAP UI5 and I am trying to develop a webpage with images and instructions. I am unable to display an image in my Webapp and need help with it. I looked through the internet and could not find any proper solution yet. Below is my code. Can you please help me understand what I am missing?
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My App</title>
<script
id="sap-ui-bootstrap"
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_belize"
data-sap-ui-libs="sap.m"
data-sap-ui-compatVersion="edge"
data-sap-ui-async="true"
data-sap-ui-onInit="module:sap/ui/demo/walkthrough/index"
data-sap-ui-resourceroots='{
"sap.ui.demo.walkthrough": "./"
}'>
</script>
<style>
.myimage{float:right !important; width:300px; height:200px;}
</style>
</head>
<body class="sapUiBody" id="content">
</body>
</html>
App.view.xml:
<mvc:View
controllerName="sap.ui.demo.walkthrough.controller.App"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
>
<Page title="Image">
<content>
<Image id="QRCode" src="images/img1.jpg" />
</content>
</Page>
</mvc:View>
App.controller.js:
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(
Controller
) {
"use strict";
return Controller.extend("sap.ui.demo.walkthrough.controller.App", {
onBeforeRendering: function() {
this.getView().byId("QRCode").addStyleClass("myimage");
},
});
});
index.js:
sap.ui.define([
"sap/ui/core/mvc/XMLView"
], function (XMLView) {
"use strict";
XMLView.create({
viewName: "sap.ui.demo.walkthrough.view.App"
}).then(function (oView) {
oView.placeAt("content");
});
});
Loading images is a little tricky, especially if you want it to run in the launchpad.
You should create the path dynamically in your controller and put it into a view model:
const sPath = sap.ui.require.toUrl("sap/ui/demo/walkthrough/images/img1.png");
const oModel = new JSONModel({ imagePath: sPath });
this.getView().setModel(oModel, "view");
<Image id="QRCode" src="{view>/imagePath}" />
Of course it's very important to pass the correct namespace to sap.ui.require.toUrl

HTMX and chart JS

I was wondering if it was possible to issue an htmx get request to an html block containing a chartJS canvas.
I have a piece of html containing a canvas generated with Chart JS that get called with an HTMX get request but I am unable to generate the chart once the get request is complete.
I have put all the dependencies of chart js in the main html but It is not working.
I also tried to put all the dependencies in the html fragment that gets called by the HTMX GET request but it is not working either.
Is it possible?
Here is what I have so far:
Original
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://unpkg.com/htmx.org#1.6.1" integrity="sha384-tvG/2mnCFmGQzYC1Oh3qxQ7CkQ9kMzYjWZSNtrRZygHPDDqottzEJsqS4oUVodhW" crossorigin="anonymous"></script>
<div id="mainAjax" class="slide-in-left-fade-in fade-me-out fade-in">
<button
class=""
hx-get="/data-viz/simple-chart"
hx-target="#mainAjax"
hx-swap="outerHTML swap:0.2s"
hx-select="#mainAjax"
hx-trigger="myEvent from:body">
Get canvas
</button>
</div>
<script>
document.body.addEventListener("myEvent", function(evt) {
alert("trigger is working")
})
</script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hammerjs#2.0.8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.2.0/chartjs-plugin-zoom.min.js" integrity="sha512-TT0wAMqqtjXVzpc48sI0G84rBP+oTkBZPgeRYIOVRGUdwJsyS3WPipsNh///ay2LJ+onCM23tipnz6EvEy2/UA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</body>
</html>
and the Canvas Im trying to fetch:
<div id="mainAjax"class="">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js" integrity="sha512-TW5s0IT/IppJtu76UbysrBH9Hy/5X41OTAbQuffZFU6lQ1rdcLHzpU5BzVvr/YFykoiMYZVWlr/PX1mDcfM9Qg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<canvas class="my-4 w-100 chartjs-render-monitor" id="myChart" width="1110" height="468" style="display: block; height: 521px; width: 1234px;"></canvas>
<script>
const ctx = document.getElementById('myChart').getContext('2d');
var config = {
type: 'line',
data: {
labels : ['2005-03-31', '2005-06-30', '2005-09-30', '2005-12-31', '2006-03-31', '2006-06-30', '2006-09-30', '2006-12-31', '2007-03-31', '2007-06-30', '2007-09-30', '2007-12-31', '2008-03-31', '2008-06-30', '2008-09-30', '2008-12-31', '2009-03-31', '2009-06-30', '2009-09-30', '2009-12-31', '2010-03-31', '2010-06-30', '2010-09-30', '2010-12-31', '2011-03-31', '2011-06-30', '2011-09-30', '2011-12-31', '2012-03-31', '2012-06-30', '2012-09-30', '2012-12-31', '2013-03-31', '2013-06-30', '2013-09-30', '2013-12-31', '2014-03-31', '2014-06-30', '2014-09-30', '2014-12-31', '2015-03-31', '2015-06-30', '2015-09-30', '2015-12-31', '2016-03-31', '2016-06-30', '2016-09-30', '2016-12-31', '2017-03-31', '2017-06-30', '2017-09-30', '2017-12-31', '2018-03-31', '2018-06-30', '2018-09-30', '2018-12-31', '2019-03-31', '2019-06-30', '2019-09-30', '2019-12-31', '2020-03-31', '2020-06-30', '2020-09-30', '2020-12-31', '2021-03-31', '2021-06-30', '2021-09-30'],
datasets: [{
label: 'AAPL Revenue',
lineTension: 0,
data: [3243.0, 3520.0, 3678.0, 5749.0, 4359.0, 4370.0, 4837.0, 7115.0, 5264.0, 5410.0, 6789.0, 9608.0, 7512.0, 7464.0, 12907.0, 11880.0, 9084.0, 9734.0, 12207.0, 15683.0, 13499.0, 15700.0, 20343.0, 26741.0, 24667.0, 28571.0, 28270.0, 46333.0, 39186.0, 35023.0, 35966.0, 54512.0, 43603.0, 35323.0, 37472.0, 57594.0, 45646.0, 37432.0, 42123.0, 74599.0, 58010.0, 49605.0, 51501.0, 75872.0, 50557.0, 42358.0, 46852.0, 78351.0, 52896.0, 45408.0, 52579.0, 88293.0, 61137.0, 53265.0, 62900.0, 84310.0, 58015.0, 53809.0, 64040.0, 91819.0, 58313.0, 59685.0, 64698.0, 111439.0, 89584.0, 81434.0, 83360.0],
backgroundColor: '#A3BE8C4D',
fill: false,
showLine : true,
borderColor:
'#A3BE8C'
,
borderWidth: 1
}],
},
}
var myChart = new Chart(ctx, config);
console.log(myChart.data.datasets)
document.body.addEventListener("cart-updated",
function (evt) {
alert("cart updated")
})
</script>
</div>

Trouble showing high-maps and high-charts on same page?

// Initiate the chart
$('#container_origin').highcharts('Map', {
title : {
text : 'Heat Map Of Visited Orgins'
},
subtitle : {
text : ''
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
colorAxis: {
min: 1,
type: 'logarithmic',
minColor: '#338ACA',
maxColor: '#1B4761'
},
series : [{
data : data,
mapData: Highcharts.maps['custom/world-highres'],
joinBy: 'hc-key',
//name: 'Random data',
states: {
hover: {
color: Highcharts.getOptions().colors[6]
}
},
dataLabels: {
enabled: true,
format: '{point.name}'
},
tooltip: {
headerFormat: '',
}
}]
});
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<!--Use this for maps/chart combo -->
<script src="http://code.highcharts.com/maps/modules/map.js"></script>
<link rel="stylesheet" type="text/css" href="chart.css">
<link href='https://fonts.googleapis.com/css?family=Nunito' rel='stylesheet' type='text/css'>
<script src="bb.js"></script>
</head>
I'm having trouble rendering highcharts and highmaps on the same page. At first, I was just getting an error but then I swapped.
<script src="https://code.highcharts.com/maps/highmaps.js"></script>
<script src="https://code.highcharts.com/maps/modules/exporting.js"></script>
<script src="https://code.highcharts.com/mapdata/custom/world-highres.js"></script>
With this -
<script src="http://code.highcharts.com/maps/modules/map.js"></script>
I now get the out line of the chart (see img). Can anybody suggest a solution?
As you can see from this getting started tutorial / Highmaps documentation for Highmaps to work you need to load, same as in Highcharts and Highstock, a framework - jQuery or Standalone Highcharts Framework and:
1) highmaps.js
<script src="http://code.highcharts.com/maps/highmaps.js"></script>
or, if you have a license for Highcharts and Highmaps, 2) highcharts.js + maps.js module
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/maps/modules/map.js"></script>
Working example:
http://jsfiddle.net/pe40p00y/14/
I have Pie, Column and Stock Charts and big trouble to integrate Map with it. I found out that these lines fix this problem:
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/maps/modules/data.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<script src="https://code.highcharts.com/stock/modules/export-data.js"></script>
<script src="https://code.highcharts.com/maps/modules/map.js"></script>
<script src="https://code.highcharts.com/mapdata/custom/world.js"></script>
This is result I got.
You have to link map as a module.
You should not use Highmaps and map module together. You can use the map modlue as a plugin with Highcharts:
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/maps/modules/map.js"></script>
Docs https://www.highcharts.com/docs/maps/getting-started

Showing loader inside a dialog popup

I have made a page in UI5 in which there is a button to open the dialog popup. On this popup page, I have some text boxes and chart, but the chart is taking so much time in loading so the entire page is displayed as white screen until the chart is loaded.
I want to show some loader for this white screen. What can be the possible solution?
(I was trying for loading a text box first and then chart but the problem is entire page is loaded together)
try below code for loader.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="UTF-8">
<title>Example Application</title>
<script id="util-coreloader"
src="util/CoreLoader.js"
data-loader-src="resources/sap-ui-core.js"
data-sap-ui-libs="sap.m"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-resourceroots='{
"com.inwerken": "../com_inwerken"
}'
data-sap-ui-xx-bindingSyntax="complex">
</script>
<script>
// execute when Core is loaded ...
CoreLoader.onReadyState(function() {
sap.ui.getCore().attachInitEvent(function () {
// .. load Component
var oComponentContainer = new sap.ui.core.ComponentContainer({
height: "100%",
name: "Example"
});
oComponentContainer.placeAt("content");
CoreLoader.ready();
});
});
</script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>

Kendo Grid Custom Reordering

I am using Kendo Grid UI. The following is an example of the same.
<!DOCTYPE html>
<html>
<head>
<title></title>
<link href="http://cdn.kendostatic.com/2013.3.1324/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2013.3.1324/styles/kendo.rtl.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2013.3.1324/styles/kendo.silver.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2013.3.1324/styles/kendo.dataviz.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2013.3.1324/styles/kendo.dataviz.silver.min.css" rel="stylesheet" />
<link href="/kendo-ui/content/shared/styles/examples.css" rel="stylesheet" />
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2012.1.515/js/kendo.all.min.js"></script>
</head>
<body>
<div id="main">
<h1 id="exampleTitle">
<span class="exampleIcon gridIcon"></span>
<strong>Grid /</strong> Column resizing </h1>
<div id="theme-list-container"></div>
<div id="exampleWrap">
<script>preventFOUC()</script>
<div id="example" class="k-content">
<div id="grid"></div>
<script>
$(document).ready(function() {
gridDataSource = new kendo.data.DataSource({
transport: {
read: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders"
},
});
$("#grid").kendoGrid({
dataSource: gridDataSource,
scrollable: true,
resizable: true,
columns: [
{
field: "OrderID",
title: "ID"
}, {
field: "OrderDate",
title: "Order Date"
},
{
field: "ShipCountry",
title: "Ship Country"
},
{
field: "ShipCity",
title: "Ship City"
},
{
field: "ShipName",
title: "Ship Name"
},
{
field: "ShippedDate",
title: "Shipped Date"
}
]
});
});
</script>
</div>
</div>
</div>
I want a customized reorder on columns. I have disabled drag and drop on OrderID. But columns other than OrderID can be reordered and these columns can be placed before OrderID column.
Is there a way where I can disable dropping of columns before OrderID?
You should do it in two steps:
Disable dropping into first column.
Disable dragging first column.
For the first part after creating the grid you can do:
$("th:nth(0)", "#grid").data("kendoDropTarget").destroy();
This gets from a grid which identifier is grid and the first head cell th:nth(0) the KendoUI DropTarget and destroys it (no longer a valid drop target).
For the second part, you should define a dragstart event that checks that you are dragging the first column and if so, you do not allow to drag it.
$("#grid").data("kendoDraggable").bind("dragstart", function(e) {
if (e.currentTarget.text() === "ID") {
e.preventDefault();
}
});
NOTE: Here I detected the first column asking for its text (ID) but you might change it to check for its position in the list of th in the grid and if so invoke preventDefault.
Check it running here: http://jsfiddle.net/OnaBai/jzZ4u/1/
check this for more elegant implementation:
kendo.ui.Grid.fn._reorderable = function (reorderable) {
return function () {
reorderable.call(this);
var dropTargets = $(this.element).find('th.disable-reorder');
dropTargets.each(function (idx, item) {
$(item).data("kendoDropTarget").destroy();
});
var draggable = $(this.element).data("kendoDraggable");
if (draggable) {
draggable.bind("dragstart", function (e) {
if ($(e.currentTarget).hasClass("disable-reorder"))
e.preventDefault();
});
}
}
}(kendo.ui.Grid.fn._reorderable);
where .disable-reorder class is for disabling column