Meteor call template method from another method - javascript

I want to call a method within a method for clientside but I don't know how to handle it, i've tried by calling like myFunction()and this.myFunction() but it is not working... This is my code
Template.decision.rendered = function () {
if ($(".active").length == 0) {
var random = Math.floor(Math.random() * 1000);
var $items = $(".item");
$items.eq(random % $items.length).addClass("active");
}
$.each($(".item"), function (index, value) {
if (Session.get($(this).attr('id'))) {
this.showResults(value.option);
}
});
};
Template.decision.showResults = function($option) {
$('#result').html('Option ' + $option + ' is voted');
};
As you can see I want to call showResults for each item inside rendered callback...

Found it using Template.decision.showResults(); silly me.

I think that a better way depending on what you are trying to do would be either to use a Session variable or a Meteor Method:
Session Variable.
Template.decision.created = function() {
Session.setDefault('showResults', false);
}
Template.decision.rendered = function() {
// [...]
$.each($(".item"), function (index, value) {
if (Session.get($(this).attr('id'))) {
Session.set('showResults', true);
}
});
}
Template.decision.showResults = function() {
return Session.get('showResults');
}
// in your template
<template name="decision">
{{#if showResults}}
<p>Here is the results.</p>
{{/if}}
</template>
Meteor Method.
// On the client.
Template.decision.rendered = function() {
// [...]
$.each($(".item"), function (index, value) {
if (Session.get($(this).attr('id'))) {
Meteor.call('showResults', function(error, result) {
if (!error and result === true) {
$('.class').hide() // It is here that you modify the DOM element according to the server response and your needs.
}
});
}
});
}
// Server-side method
// But, if you want it to react like a stub, put it inside your lib folder.
Meteor.methods({
showResults: function() {
// do your thing
result = true; // let's say everything works as expected on server-side, we return true
return result;
}
});

Related

Retrieving elements from an array using events in Meteor

I am getting [object, object] instead the elements from the array in the 'categories' function. Though I am not sure, perhaps this is expected and I am just getting it wrong.
if (Meteor.isClient) {
Template.ipsosboard.helpers({
'categories': function() {
return array; // Some data stored as JS Object in lib.
},
'currentElement': function() {
return Session.get('selectedEvent');
}
});
Template.ipsosboard.events({
"change #category-select": function(event, template) {
var selectedEvent = $(event.currentTarget).val();
Session.set('selectedEvent', selectedEvent);
console.log("EventNum: " + selectedEvent);
}
});
}; //end of client code.
if (Meteor.isServer) {
//code to run by server here.
};
This seems to fix it. It needed to convert the object into an array. Note: the 'data' is a json file stored as a JS object in lib folder of the project, thus I needed to convert it.
if (Meteor.isClient) {
Template.ipsosboard.helpers({
'categories': function() {
It needed to be converted to array using the function below.
var myObj = data;
var array = $.map(myObj, function(value, index) {
return value;
});
return array;
},
So now it returns the data as required.
'currentElement': function() {
return Session.get('selectedEvent');
}
});
Template.ipsosboard.events({
"change #category-select": function(event, template) {
var selectedEvent = $(event.currentTarget).val();
Session.set('selectedEvent', selectedEvent);
console.log("EventNum: " + selectedEvent);
}
});
}; //end of client code.
if (Meteor.isServer) {
//code to run by server here.
};

When I use $scope.watch in angular, I have an issue in passing data

I use $scope.watch and set and get to pass one data from one controller to another. This works fine, but when I do this with different html files, data is not transferred in my first click. because browser is refreshed. But when I click go back arrow in chrome and set a value and clicked, I can get the value in my second page. How can I resolve this. Please tell me solution.
var data = {
Quantity: ''
};
return {
getQuantity: function() {
return data.Quantity;
},
setQuantity: function(quantity) {
data.Quantity = quantity;
}
};
.controller('DetailsCtrl', function($scope, $http, Data) {
$scope.quantity = '';
$scope.$watch('quantity', function(newValue50, oldValue50) {
if (newValue50 !== oldValue50)
Data.setQuantity(newValue50);
});
})
.controller('FifthCtrl', function($scope, $http, Data) {
$scope.$watch(function() {
return Data.getQuantity();
}, function(newValue50, oldValue50) {
if (newValue50 !== oldValue50)
$scope.quantity = newValue50;
});
})
If you want to store the value between different sessions in the browser you could add the quantity value to the local storage.
Here's an angularjs service/factory example
app.factory('Data', function () {
var data = {
Quantity: ''
};
return {
getQuantity: function () {
if (localStorage.getItem("data") === null) {
data.Quantity = 0;
} else {
var jsonData = localStorage.getItem('data');
data.Quantity = JSON.parse(jsonData);
}
return data.Quantity;
},
setQuantity: function (quantity) {
data.Quantity = quantity;
localStorage.setItem("data", JSON.stringify(data));
}
};
});
Note 1: You actually don't need the object 'data' in this case as you store the value in the storage but I let it stand as is.
Note 2: The localStorage can't store complext types such as objects and you need to make strings of them before you store them, thats why the JSON.stringify() is used.

Access function in module with similar name of function in another module

Code:
for (var i in RESTCalls_GET) {
describe('Retrieve all Product Component names and their IDs', function() {
var restCalls;
beforeEach(function() {
RESTCalls_GET.setClient(mockClient);
restCalls = new Rest_calls(mockClient);
});
describe(i + '()', function() {
it('should return data if response code is 200', function(done) {
mockClient.mockURLForSucceed(eval('restCalls.' + i + "_RESTCall"), eval('RESTCalls_GET_ExampleData.' + i + "_ExampleData"), 200);
eval('RESTCalls_GET.' + i)(function(result) {
result.should.equal(eval('RESTCalls_GET_ExampleData.' + i + "_ExampleData"));
done();
});
}),
it('should return error if response code is NOT 200', function(done) {
mockClient.mockURLForError(eval('restCalls.' + i + "_RESTCall"), null, TestData.RESTCallResponseError_Test);
eval('RESTCalls_GET.' + i)(function(errorObj) {
errorObj.should.have.property('errorCode');
done();
});
});
});
});
}
I am looping though functions in RESTCalls_GET. Say, for example, i = getComponent, a function called getComponent_RESTCall will be in module restCalls
I have been told that one way to accomplish this is by using eval() (even though it is not recommended). This way is not working and when I debug, the parameters which use eval() in mockURLForSucceed are undefined.
This obviously causes all my tests to fail.
Any suggestions appreciated.
EDIT: (additional information)
var mockClient = function() {
var urlMap = {};
return {
get: function(url, callback) {
var entry = urlMap[url];
if (entry) {
callback(entry[0], entry[1]);
} else {
console.error("Unable to match URL " + url);
}
return {
on: function() {
//Ignore
}
};
},
mockURLForSucceed: function(URLofRESTCall, succeedData, succeedRes) {
urlMap[URLofRESTCall] = [succeedData, {statusCode: succeedRes}];
},
mockURLForError: function(URLofRESTCall, errorData, errorRes) {
urlMap[URLofRESTCall] = [errorData, errorRes];
}
}
}();
EDIT: (half way there)
I've resorted back to eval() an got the function/variable name required in format file.functionName by this:
var RESTCallURL = eval('"restCalls." + i + "_RESTCall"');
var RESTCallData = eval('"RESTCalls_GET_ExampleData." + i + "_ExampleData"');
The problem I'm having now if that these are strings. So when I pass them into a function, it gets that string value and not the one it equals in it's own function, does that make sense?
What I mean is that if I passed in RESTCallURL into a function now, then the value of that parameter would be restCalls.whatever_RESTCall whereas before it got the URL of the REST Call I am calling (http://whatever). Since I now have the name of the function, am I able to search for functions in my project by that name?
This task seems so simple to do and I think I am over thinking it.
I don't think you need eval there, what about using
RESTCalls_GET[i](function(result) {
result.should.equal(RESTCalls_GET_ExampleData[i + '_ExampleData']));
done();
});
You could easily test this behaviour by defining the following in your browser console
var test = {
'some-function': function() { console.log('works'); }
};
test['some-function']();

Display deferred data in template

Problem
I'm using this 20 line router to do my routing and templating.
What I am struggling with is using data in the template.
My templating engine is https://github.com/trix/nano.
What I have
I have a function that gets the users data (at the moment I am just trying to show a message):
adrLoadAddressBooks:function() {
var deferred = new $.Deferred();
var return_response = {};
data = {
country_code:config.country_code,
language_code:config.language_code,
source:config.source,
usr_id:app.getCookie('usr_id'),
login_token:app.getCookie('login_token')
};
app.api('adr/list',data,function(data) {
var response = JSON.parse(data);
return_response.msg = 'This user has address books.';
if(!response.result) {
return_response.msg = 'No address books found.'
}
deferred.resolve(return_response);
},'post');
return deferred.promise();
},
In my router, I get the data like so:
jsRouter.route('/adr','adr/index',function() {
console.log('In route function');
this.response = events.adrLoadAddressBooks().done(function(response) {
console.log(response);
return response;
});
});
The console.log returns the following:
Object {msg: "This user has address books."} // correct
And in my template file I have the following:
<h4>Address Books</h4>
Message: {response.msg}
Create Address Book
Question
It currently only displays the template, no msg. If I change {response.msg} to just {response}, it displays [Object object] which is the response object so it is sending something.
How do I access the msg?
I fixed it by changing my router quite a bit. I have a loadPage() function that looks like this:
loadPage:function(page,element,bindData) {
$.get(page,function(data) {
element.html(nano(data, bindData));
app.setPageListeners();
});
},
This was called at the end of my router() function (after the template has been found).
router:function() {
app.resetResponse();
jsRouter.el = jsRouter.el || $('#view');
var url = $.urlHash() || '/';
if(typeof route == 'undefined' || typeof route == null) {
route = jsRouter.routes['404'];
}
auth.isLoggedIn();
if(jsRouter.el && route.controller) {
jsRouter.loadPage(config.templates + route.template + '.html',jsRouter.el,new route.controller);
}
},
Firstly, what I did was changed my actual route() function like so:
route:function(path,template,callback) {
jsRouter.routes[path] = {template: template, callback: callback };
},
So now I can pass a callback by setting up my route like this:
jsRouter.route('/adr','adr/index',events.adrLoadAddressBooks);
I then changed the end of my router to this:
if(jsRouter.el) {
if(route.callback) {
jsRouter.loadData(config.templates + route.template + '.html',jsRouter.el,route.callback);
} else {
jsRouter.loadPage(config.templates + route.template + '.html',jsRouter.el,"");
}
}
And then created a loadData function that waits for a deferred object before continuing, like so:
loadData:function(page,element,callback) {
if(typeof callback !== 'undefined') {
if (typeof callback === "function") {
callback().done(function(data) {
jsRouter.loadPage(page,element,data);
});
} else {
alert("Could not call " + endpoint);
}
} else {
jsRouter.loadPage(page,element,this);
}
},
My callback, in this case, looks like this:
adrLoadAddressBooks:function() {
var deferred = new $.Deferred();
//do stuff
app.api('adr/list',data,function(data) {
var response = JSON.parse(data);
return_response.msg = 'Below is a list of all your address books.';
if(!response.result) {
return_response.msg = 'This user has no address books.';
deferred.resolve(return_response);
}
//build response
deferred.resolve(return_response);
},'post');
return deferred.promise();
},
And it works quite well. :) Obviously, if there's stuff that I can improve, add a comment
EDIT 1
Added extra step after route function.
EDIT 2
Full router available on Pastebin

Anonymous function causing ids to not be set after AJAX success

I'm making an AJAX call from within an Anonymous function. When the success callback takes place I'm then able to set my custom JS objects ids and other important info that has arrived from the data server.
After I set the a.target.id to the returned data.id everything looks fine.
On the step where I'm calling a function to do some work with the newly updated custom JS object, that I just updated with the response data from the server. I am passing the parent of that object to the method to do some work on all the children of that object.
However, as you can see on the last example in the snap shot photos the a.target.parent.children[0].id is not in the collection and/or it's ids where never set.
I must be losing a reference to that object during the AJAX call when using an Anonymous function.
Here is all of the code. How am I losing the reference? Or how can I maintain a reference to that parent's children when the AJAX call returns?
I've never had this happen before, makes me believe that it has something to do with the Anonymous function.
var horizontalPositioner = function (horizontals) {
var hpa = ['?horPositions='];
for (var i = 0; i < horizontals.children.length; i += 1) {
hpa.push(horizontals.children[i].id + ':' + horizontals.children[i].position + ',');
};
hpa[i] = hpa[i].replace(',', '');
dataBase.update(dbPart('horizontal' + hpa.join('')));
};
this.subscribe.call(this, e.horizontaladded, function (a, fn) {
//
if (!a.extra.owner.id) {
return;
};
(function (a) {
dataBase.insert(
dbPart(
['horizontal?a=', a.extra.owner.instanceName, '&id=', a.extra.owner.id].join(''),
a.target
),
dbCB(
function (data, status) {
if (status === 'error') { return; };
a.target.id = data.id,
a.target.HTML().addClass('alum_' + data.id),
a.target.finish.id = data.finishID,
a.target.size.id = data.sizeID,
a.target.siteLine.id = data.sitelineID;
//
//reposition horizontals
// setTimeout(function () { horizontalPositioner(a.target.parent); }, 1000);
debugger
horizontalPositioner(a.target.parent);
if (fn) { processCallbacks(data, status, fn); };
//very last
events.publishDatabaseCallbacks(e.horizontaladded,
eArgs(a.bay, { data: data, instanceName: 'horizontal', ownerid: a.extra.owner.id, id: data.id }));
},
function (xhr, status, errorThrown) { console.log('ERROR adding horizontal'); })
);
}(a));
}, true);
I've added an anonymous function with a nested setTimeout to give everything time to build. I've got many events taking place at once, so for now this works.
var horizontalPositioner = function (horizontals) {
(function (hors) {
setTimeout(function () {
var hpa = ['?horPositions='];
for (var i = 0; i < hors.children.length; i += 1) {
hpa.push(hors.children[i].id + ':' + (hors.children[i].position ? hors.children[i].position : 1) + ',');
};
hpa[i] = hpa[i].replace(',', '');
dataBase.update(dbPart('horizontal' + hpa.join('')));
}, 1000);
}(horizontals));
};

Categories

Resources