SAPUI5: Cannot read property 'call' of undefined on elementBinding - javascript

I'm trying to do some operations after a successful data binding of the view. The best idea would be in my opinion to do it in the callback of the attachModelContextChange method. After defining which method would be the callback and attaching the event listener to the view, when I try to bind data to my view, I get the error: Cannot read property 'call' of undefined. I'm pasting my controllers code fragments below and the stack trace.
onInit: function() {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.attachRouteMatched(this.routeMatched, this);
},
routeMatched: function(oEvent) {
var sEntityPath,
oParameters = oEvent.getParameters();
this.routeName = oParameters.name;
this.getView().detachModelContextChange(
this.modelCallback('edit'),
this.getView()
);
if (oParameters.name === "EditItem") {
if (!isNaN(oParameters.arguments.id)) {
this.getView().attachModelContextChange(null,
this.modelCallback('edit'),
this.getView()
);
sEntityPath = "/ItemData(" + oParameters.arguments.id + ")";
this.getView().bindElement(sEntityPath);
} else {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("CreateItem", {
from: "EditItem"
}, false);
}
}
},
modelCallback: function(type) {
console.log(type);
}
The console.log from the modelCallback method is launching properly. Removing the line with
this.getView().bindElement(sEntityPath);
prevents the error from triggering (but this way I'm of course not getting any data in my view).
Any ideas what am I missing?
Below I'm pasting the stack trace:
datajs.js:17 Uncaught TypeError: Cannot read property 'call' of undefined
at f.a.fireEvent (sap-ui-core.js:449)
at f.a.fireEvent (sap-ui-core.js:991)
at f.fireModelContextChange (sap-ui-core.js:573)
at f.h.setElementBindingContext (sap-ui-core.js:524)
at constructor.i (sap-ui-core.js:500)
at constructor.a.fireEvent (sap-ui-core.js:449)
at constructor.B._fireChange (sap-ui-core.js:1302)
at eval (library-preload.js:2375)
at u (library-preload.js:2460)
at d.r._processSuccess (library-preload.js:2492)

You have incorrect parameters in attachModelContextChange call. The only required parameter is a callback function, modelCallback in your case. You pass null as oData optional parameter which can be omitted. The correct call should look like this:
this.getView().attachModelContextChange(
this.modelCallback, // the function, not the result of its call!
this // Instance of controller (not View!), which is now *this*
);
Also, the call of detachModelContextChange should be with the same parameters to make it work:
this.getView().detachModelContextChange(
this.modelCallback, // the function, not the result of its call!
this // Instance of controller (not View!), which is now *this*
);
when you place this.modelCallback('edit') at the parameter list then first the function is executed and then its result is passed as a parameter to attachModelContextChange (or detachModelContextChange)

onRowSelect:function(oAnubhav){
//alert("Yes, Row Selection Worked Roger !");
//step1 get the path of the selection item.
debugger;
var sPath= oAnubhav.getParameter("rowContext").getPath();
//step2 transfer the element data to the simpleformcontrol,using bind element.
//2.1 get the object of simpleform-parent of all input.
// var oSimple=this.getView().byId("idSimple");
//2.2the entire simpleform new recives data form table elementselected.
//oSimple.bindElement(sPath);
this.getView().bindElement(sPath);
},

Related

'invoke a function as a method' that is within another 'function as a method'

I have inherited some javascript code that I am struggling to work with. I believe I need to 'invoke a function as a method' that is within another 'function as a method'. I have included abridged code below.
drawer = {
...
ChartDrawer: function(var1,var2,etc)
{
...
this.drawChart = function(node)
{
...
$(this.jqValToggle + ' #valuation-box').click(function(){
console.log('clicked');
drawer.valToggle();
var targetNode = addrFromRawAddr(rawAddr)
showNarrative(targetNode);
/// THIS IS WHERE I'D LIKE TO CALL drawChart FROM
});
}
}
Could you please suggest the syntax needed to call 'drawChart' from the location in the code specified above.
I would have thought I could use drawer.ChartDrawer.drawChart(node); but this gets 'Uncaught TypeError: drawer.ChartDrawer.drawChart is not a function'. I have also tried variations on using 'this.drawChart' with no success
Try this:
$(this.jqValToggle + ' #valuation-box').click(function(){
/* ... */
this.drawChart();
}.bind(this));
By forcing the click handler to run in the current context, rather than in the context of the clicked element, we retain access to the drawChart method.

Knockout.js unable to process binding: undefined is not a function?

I'm trying to implement a custom binding for an accordion-like document layout on a webpage, but I'm encountering an issue I can't easily solve.
Immediately on page load, I am presented with the error:
Uncaught TypeError: Unable to process binding "accordion: function (){return currentAccordionSection }"
Message: undefined is not a function
I have tried declaring my observable as both a function and normally in the data-bind syntax without success. I have initialized my observable with a default value (null) and it has not fixed this issue. Below is my entire ViewModel:
var libraryViewModel = function () {
var self = this;
ko.bindingHandlers.accordion = {
update: function (element, valueAccessor) {
console.log(ko.unwrap(valueAccessor()));
var value = ko.unwrap(valueAccessor());
var section = $(element.text());
//ko.bindingHandlers.css.update(element, function () {
// if (value === section) {
// return 'library-section-active';
// }
//});
//ko.bindingHandlers.css.update($(element).children('i:last-child').get(0), function () {
// if (value === section) {
// return 'fa fa-chevron-up';
// } else {
// return 'fa fa-chevron-down';
// }
//});
}
}
self.currentAccordionSection = ko.observable(null);
self.updateAccordionSection = function (section) {
self.currentAccordionSection(section);
}
}
Some of the code above is commented out as it is not relevant to the problem at hand and I have disabled it to implement a reduced test case to narrow down the problem. Here is my binding declaration:
<h2 class="library-header" data-bind="accordion: currentAccordionSection, click: updateAccordionSection.bind('Text')">
What exactly am I doing wrong?
The problem is this line:
var section = $(element.text());
as per knockout's documentation
element — The DOM element involved in this binding
text is a jQuery function not a DOM function so I think you are looking for something like:
$(element).text() or $($(element).text()) instead? I'd assume the former since it makes more sense.
As for the nested binding handler I'm not sure why that is in the viewmodel since it's exposed on the knockout global object you're not protecting yourself from anything just making your code more unreadable. They are designed to be resuable so you can use them with different viewModels

Using Knockout push in a function returns an error

In this example, I'm using knockout with require.js.
Outside Main.roll(), Main.result.push works as expected. Inside the function, it throw an error: Uncaught TypeError: Cannot read property 'apply' of undefined.
I can still access Main.result() in the function. I can set values to it, but I can't use .push for some reason.
define(['knockout', 'd20'], function(ko, d20) {
return function main() {
var Main = this;
Main.result = ko.observableArray('');
Main.result.push( d20.roll('2d8+2') ); // works
Main.roll = function() {
Main.result('');
Main.result.push( d20.roll('2d8+2') ); // no workie
}
}
});
The syntax is incorrect. You are dealing with an array so you can't set it to empty string. Following are the two ways for initializing the array:
Either this :
Main.result = ko.observableArray([]);
or this :
Main.result = ko.observableArray();
However, if you wish to reset it to empty array use the code snippet below:
Main.result([]);

Uncaught TypeError: object is not a function (calling onchange function)

My code is big so I will keep it short. I am tring to fire onchange event of Select atribute. Problem is that when I fire it I got this error:
Uncaught TypeError: object is not a function
Since my code is big I will show to you codes where I decalare onchange event and when I fire it.
Here is when onchange function is declared:
function e(b, c) {
function a() {
if (b.current_modal) {
b.current_modal.className = "hide"
}
f("overlay").className = "hide"
}
jigsaw.UI.close_lightbox = a;
Util.$("overlay").click(a);
Util.$("set-parts").change(function () {
if (this.parts != 9) {
jsaw.set_image("images/puzzle.jpeg")
} else {
jsaw.set_image("images/puzzle1.jpeg")
}
c.emit(jigsaw.Events.PARTS_NUMBER_CHANGED, +this.value);
c.emit(jigsaw.Events.RENDER_REQUEST)
});
Util.$("game-options").click("a", function (h) {
if (jigsaw.Events[this.id]) {
h.preventDefault();
c.emit(jigsaw.Events[this.id])
}
})
}
and here is when I fire onchange event:
show_time: function () {
/*.....*/
javascript: document.getElementById("date").innerHTML = ScoreResult;
document.getElementById("set-parts").selectedIndex = 1;
document.getElementById('set-parts').onchange();
}
I don't use jquery, but in JavaScript there is a difference on how addEventListener(eventName, ...) and on*eventName* = function(){} works.
I suppose that not modern library will use on*eventName* interface for one simple reason: I can hold just a single listener. But the on*eventName* are still there to support legacy code.
Now, in your particular case, when you add the event your library is using the addEventListener/removeEventListener/dispatchEvent underline DOM interface. This will not set up the legacy on*eventName* property to your callback, so the only way you can directly call it it by dispatching an event with the DOM method dispatchEvent (or your library wrapper) with an Event object with type 'change'. That is what "new Event('change')" does. If you need to pass extra properties to the event you can create it like this:
new Event('change', { foo : 1, bar : 'hello, world!' })
and those properties will be available in your listener callback arguments[0] under whichever name you set your argument (in your case, you left it empty).

JS TypeError: Cannot read property 'map' of undefined

I'm getting a "Cannot read property of undefined" error in the following code.
What happens is that the initFromServer() is called which goes to get the model from the server. But what ends up happening is that when init() is called, the parameter model is undefined. Using console.log to determine what is going on it seems that it never reaches the Proxy.getModel() function before it determines that model is undefined.
I'm not entirely sure what is going on. There are a lot of other functions and what not that I have not inserted. Hopefully it makes sense.
ClientModel.prototype.initFromServer = function(success) {
this.getProxy().getModel(this.init(), success());
}
ClientModel.prototype.init = function(model) {
this.setMap(new catan.models.Map(model.map.radius));
};
In the proxy file we have:
Proxy.prototype.getModel = function(update, success) {
jQuery.get("/game/model", function(data) {
update(data);
success(data);
});
};
When you invoke init() in initFromServer() you do not pass any arguments.
In the init() function you access model as first argument …
ClientModel.prototype.initFromServer = function(success) {
this.getProxy().getModel(this.init(), success());
|
+---- No Argument.
}
ClientModel.prototype.init = function(model) {
|
v
this.setMap(new catan.models.Map(model.map.radius));
|
+----> Ups.
};

Categories

Resources