I have debugged my code for almost 2 hours as well as try to solve it by using this site Object but it does work. It seems there is an issue with the Controller model. The following is snapped from the code
var budgetController = (function () {
var number = 23;
})();
var UiController = (function () {
// get the html input (read the data )
// you can return whather var by var or retuen one object that has all the HTML compenents
var DOMStrings = {
inputType: '.add__type',
inputDesc: '.add__description',
inputValue: '.add__value',
inputBtn: '.add__btn'
};
return {
getInput: function () {
return {
type: document.querySelector(DOMStrings.inputType).value, // Will be either inc or exp
description: document.querySelector(DOMStrings.inputDesc).value,
value: document.querySelector(DOMStrings.inputValue).value
};
},
getDOMStrings: function () {
return DOMStrings;
}
};
})();
var Controller = (function (budgetCtr, UICtrl) {
// Immediately Invoked Function Expression
var DOM = UICtrl.getDOMStrings();
var CtrAddItem = function () {
// pass everthing to here
var output = UICtrl.getInput();
console.info("Data " + output);
}
document.querySelector('.add__btn').addEventListener('click', CtrAddItem);
document.addEventListener('keypress', function (event) {
if (event.keyCode === 13 || event.which === 13) {
CtrAddItem();
}
});
})(budgetController, UiController);
The [Object , Object] appeared whenever I console log the output on the controller model
Whenever you concat a string and an object using + the toString-method is called on the object (which by default just returns [object Object]). You should pass the object as the second argument instead:
console.info("Data", output);
Related
I have the following self-invoked function which is being utilized by the other functions across the app:
var Api = (function() {
var requestPayload;
var responsePayload;
return {
getRequestPayload: function() {
return requestPayload;
},
setRequestPayload: function(newPayloadStr) {
requestPayload = JSON.parse(newPayloadStr);
},
getResponsePayload: function() { // <-Function's output I need
return responsePayload;
},
setResponsePayload: function(newPayloadStr) {
responsePayload = JSON.parse(newPayloadStr);
}
};
}());
This function is called by other functions in the app like:
Api.getResponsePayload();
I want to capture the output of getResponsePayload function every time this function is called to utilize is for further processing.
I tried to create another function:
function runMe(responsePayload) {
console.log(responsePayload)
}
And it gets called everytime getResponsePayload function is called but the output I'm getting is undefined:
getResponsePayload: function() {
runMe();
return responsePayload;
How can I get the output of getResponsePayload function everytime it gets called by any other function in the app?
Just shim it, assuming this is for debug purposes. You may want to handle exceptions more explicitly, just be sure to rethrow to be transparent.
Api.getResponsePayload = (function(previousFn){
return function() {
var result = previousFn.apply(this, arguments);
// print them or something
return result;
}
})(Api.getResponsePayload)
Edit: Here is a generalisation of the method above:
function logMethodCallsOn(object, methodName) {
var actualMethod = object[methodName];
object[methodName] = function() {
var title = methodName + "(" + Array.prototype.map.call(arguments, function (val) { return JSON.stringify(val); }).join(", ") + ")";
try {
var result = actualMethod.apply(this, arguments);
console.log(title + " =", result);
return result;
} catch (e) {
console.error(title + " threw", e);
throw(e);
}
}
}
logMethodCallsOn(Api, 'getResponsePayload');
logMethodCallsOn(Api, 'setResponsePayload');
You could use callbacks. I'm not sure if you whant a callback in the get or the set, this example shows both.
Eric's answer is more elegant and can be used even if Api is an external object. But I think this simpler implementation could be useful for learning purpose.
var Api = (function(getResponsePayloadCallback, setResponsePayloadCallback) {
var requestPayload;
var responsePayload;
return {
getRequestPayload: function() {
return requestPayload;
},
setRequestPayload: function(newPayloadStr) {
requestPayload = JSON.parse(newPayloadStr);
},
getResponsePayload: function() { // <-Function's output I need
getResponsePayloadCallback(responsePayload);
return responsePayload;
},
setResponsePayload: function(newPayloadStr) {
responsePayload = JSON.parse(newPayloadStr);
setResponsePayloadCallback(responsePayload);
}
};
})(getResponsePayloadHandler, setResponsePayloadHandler);
Api.setResponsePayload('{ "foo": "foo value" }');
var requestPayload = Api.getResponsePayload();
function getResponsePayloadHandler(value) {
console.log("getResponsePayload: " + value.foo);
}
function setResponsePayloadHandler(value) {
console.log("setResponsePayload: " + value.foo);
}
You are not passing any parameter to runMe so it logs undefined. Change your getResponsePayload function to:
getResponsePayload: function() {
runMe(responsePayload);
return responsePayload;
}
Anyway be aware that if you don't set responsePayload, you console output will still be undefined cause responsePayload is only declared but never assigned a value (so it will have undefined value)
Following is my javaScript code.
var myObjfn = {
before : function(){
console.log("before");
},
loadA: function(){
console.log("loadA");
},
loadB: function(){
console.log("loadB");
},
loadC: function(){
console.log("loadC");
}
}
Whenever I call myObjfn.loadA(), it should call myObjfn.before() method before executing loadA method. Same for loadB() & loadC(). I don't want to explicitly call before() method in all loadA,loadB and loadC methods. Is there any option to achive this in javascript ?
You could do something like this. Which creates a wrapper function for each function in the object except the before function.
var myObjfn = { ... };
Object.keys(myObjfn).forEach(key => {
if (key === "before") return;
var oldFunc = myObjfn[key];
myObjfn[key] = function() {
myObjfn.before();
return oldFunc.apply(this, arguments);
};
});
myObjfn.loadA();
// "before"
// "loadA"
I am currently working on javascript Function and Objects but there is a little bit confusion.
I have created an object and called its method in the window like
obj.something();, it gives me result but when I write same code in console like console.log(obj.something());, it gives me undefined in the console
So, my question is obviously why & how?
var obj ={
value: 1,
increment: function () {
this.value += 1
// return this
},
add: function (v) {
this.value += v
// return this
},
shout: function () {
console.log(this.value);
// return this
}
};
obj.shout();
console.log(obj.shout());
undefined is the default return value from a function without return.
From MDN docs of return statement:
When a return statement is called in a function, the execution of this function is stopped. If specified, a given value is returned to the function caller. If the expression is omitted, undefined is returned instead.
You hava to return value from function ,Like this
var obj ={
value: 1,
increment: function () {
this.value += 1
// return this
},
add: function (v) {
this.value += v
// return this
},
shout: function () {
return this;
}
};
obj.shout();
console.log(obj.shout());
You can remove the display of "undefined" without adding a "return" by using the .call() instead of using () in a function.
var obj ={
value: 1,
increment: function () {
this.value += 1
// return this
},
add: function (v) {
this.value += v
// return this
},
shout: function () {
console.info("Line-14");
console.log(this.value);
console.info("Line-16");
//return;
}
};
var objectShootResult = obj.shout;
console.info("Line-21");
objectShootResult.call(obj);
console.info("Line-22");
I'm trying to test one of my functions, but part of it uses a private variable from the controller.
How can I get Jasmine to fake the data from that private variable?
window.MyApp = window.MyApp || {};
(function(myController) {
var deliverablesKoModel;
myController.initialize = function(releaseId) {
// Ajax call with this success:
deliverablesKoModel = new knockOutModel(data); // this model contains an observable array named 'deliverables'
};
myController.checkDeliverableNameIsValid = function (deliverable) {
var valid = false;
if (ko.unwrap(deliverable.name) !== null && ko.unwrap(deliverable.name) !== undefined) {
// PROBLEM HERE
// when running the test deliverablesKoModel below is always undefined!
/////////////
valid = _.all(deliverablesKoModel.deliverables(), function(rel) {
return (ko.unwrap(rel.name).trim().toLowerCase() !== ko.unwrap(deliverable.name).trim().toLowerCase()
|| ko.unwrap(rel.id) === ko.unwrap(deliverable.id));
});
}
deliverable.nameIsValid(valid);
return valid;
};
}(window.MyApp.myController = window.MyApp.myController || {}));
My Jasmine test. I tried having deliverablesKoModel be a global variable but it's always out of scope when hitting the method above.
describe("checkDeliverableNameIsValid should", function () {
var deliverable;
beforeEach(function () {
window['deliverablesKoModel'] = {
deliverables: function() {
return fakeData.DeliverablesViewModel.Deliverables; // this is a json object matching the deliverables in the knockout model
}
};
deliverable = {
id: 1,
name: "test 1",
nameIsValid: function(isValid) {
return isValid;
}
};
});
it("return false if any deliverable already exists with the same name", function () {
var valid = myApp.myController.checkDeliverableNameIsValid(deliverable);
expect(valid).toBe(false);
});
});
deliverablesKoModel is private to code outside of your IIFE.
I am not familiar with knockout, but there are a few ways to set deliverablesKoModel.
Make it a property of your controller that you can set/get.
Make your controller #initialize method accept a callback function which can return an instance of your model. Then, you can send in a function when calling #initialize on your controller in your test.
Example for approach #2 above:
var deliverablesKoModel;
myController.initialize = function(releaseId, modelCallback) {
// Ajax call with this success:
deliverablesKoModel = modelCallback(data); //returns a model
};
Spec:
it("return false if any deliverable already exists with the same name", function () {
var fakeModel = function(data) {
return {
deliverables: function() {
return fakeData.DeliverablesViewModel.Deliverables;
}
}
};
//You didn't initialize your
//controller, which made the "private" variable deliverablesKoModel null in your IIFE
myApp.myController.initialize(relaseId, fakeModel);
var valid = myApp.myController.checkDeliverableNameIsValid(deliverable);
expect(valid).toBe(false);
});
Here is what I have inside a backbone model:
defaults: {
prayer_string: function (){
var label_val = $("#prayer_type_label").val();
console.log("Prayer_string returning: ", label_val);
return label_val;
}
}
But when I access the model like so:
var prayerString = model.prayer_string;
prayerString is the function and not the return label_val.
What do I need to do to get the return value of the function instead of the function itself?
Thanks,
Andrew
Try this instead:
var yourModel = new (Backbone.Model.extend({
prayer_string: function () {
var label_val = $('#prayer_type_label').val();
console.log('Prayer_string returning: ' + label_val); // use + for concatenating strings
return label_val;
}
});
var prayerString = yourModel.prayer_string(); // invoke the method with ()