I've got every time a type error that a function definition could not be found. The code looks as follow:
return BaseController.extend("ch.micarna.weightprotocol.controller.Calendar", {
onInit: function () {
console.log(this._isDateType(new Date()));
let oHbox = this.byId("calendar-container");
let oTodayDate = new Date();
let oEndDate = this._getLastDayOfMonth(oTodayDate);
},
_getLastDayOfMonth: (oBegin) => {
if (this._isDateType(oBegin)) {
throw new TypeError("The given parameter is not type of date.");
}
return new Date(oBegin.getFullYear(), oBegin.getMonth() + 1, 0);
},
_isDateType: (oDate) => {
return Object.prototype.toString.call(oDate) === "[object Date]";
},
});
The problem is the _isDateType
function that could not be found when it is called inside the _getLastDayOfMonth
function.
I set the break point:
and as you can see, the function is undefined and I do not know why.
At the beginning of the onInit
function, I called the _isDateType
function:
console.log(this._isDateType(new Date()));
and it supply the result as expected.
What am I doing wrong?
Replace the arrow function
_getLastDayOfMonth: (oBegin) => {
// this....
},
with the normal function expression:
_getLastDayOfMonth: function(oBegin) {
// this...
},
By this, the _getLastDayOfMonth
can freely access other methods within the Controller instance.
Why it didn't work with arrow function
First of all, it's important to know that arrow functions bind their context lexically.
An arrow function expression has a shorter syntax than a function expression and does not have its own this
. [source]
For example, it's not possible to call .bind
on arrow functions. They get their this
from the closure when evaluated.
- Since
this
was not an instance of the Controller but rather the window
object when BaseController.extend
was called, calling this._isDateType
inside the arrow function was equivalent to window._isDateType
.
What you cannot do is refer to a property of an "under construction" object from elsewhere in the object literal syntax. In cases where you want to do that, you do need one or more separate assignment statements.
For example, move your code as follows:
var temp = BaseController.extend("ch.micarna.weightprotocol.controller.Calendar", {
onInit: function () {
console.log(this._isDateType(new Date()));
let oHbox = this.byId("calendar-container");
let oTodayDate = new Date();
let oEndDate = this._getLastDayOfMonth(oTodayDate);
}
});
temp._isDateType = (oDate) => {
return Object.prototype.toString.call(oDate) === "[object Date]";
};
temp._getLastDayOfMonth = (oBegin) => {
if (this._isDateType(oBegin)) {
throw new TypeError("The given parameter is not type of date.");
}
return new Date(oBegin.getFullYear(), oBegin.getMonth() + 1, 0);
}
return temp;
The idea is to split function assignments into several statements;
The element this can be used inside a function to get the temporary value of the element. To use the _isDateType
method you should create an attribute inside the method and fill it with the 'this' value.
return BaseController.extend("ch.micarna.weightprotocol.controller.Calendar", {
var temp= null;
onInit: function () {
temp = this;
console.log(temp._isDateType(new Date()));
let oHbox = temp.byId("calendar-container");
let oTodayDate = new Date();
let oEndDate = temp._getLastDayOfMonth(oTodayDate);
},
_getLastDayOfMonth: (oBegin) => {
if (temp._isDateType(oBegin)) {
throw new TypeError("The given parameter is not type of date.");
}
return new Date(oBegin.getFullYear(), oBegin.getMonth() + 1, 0);
},
_isDateType: (oDate) => {
return Object.prototype.toString.call(oDate) === "[object Date]";
}