Solved.
It turned out to be something else completely.
Thanks for everyone that tried to help, you guys rule!
I'll take a guess here but would need to see your code to make sure I'm giving you a good answer :-). You can't prevent a reactive data source from triggering an invalidation, but you can run some code in a nonreactive callback to make sure that code is NOT rerun.
Here are two examples to illustrate what's happening.
Template.myTemplate.helpers({
post: function () {
var someReactiveVar = Session.get('value');
return Posts.findOne({_id: 5});
}
});
In the above example, a change to post 5, or to Session's value will trigger the template to re-run. Let's say we want the template to re-run only for changes to the post, but not for the session variable. We could do this:
Template.myTemplate.helpers({
post: function () {
var someNonReactiveVar = Deps.nonreactive(function () { return Session.get('value'); });
return Post.findOne({_id: 5});
}
});
Now, just because we call Session.set('value', 'some other value') the template will not be re-run because we wrapped the get call inside a Deps.nonreactive callback.
Have you seen the answer to this question? Sounds like what you are looking for
Meteor.js - temporarily prevent a template from re-rendering (disable reactivity)
Related
I have a function that does some gui-logic, and I need this to run every time meteor updates a template reactively.
I tried putting the code in the Template.myTemplate.helpers, like shown below, but then nothing works at all.
Template.ResourceManager.helpers({
names : function(){
myFunction();
return resources.findOne({age : 20}).names;
}
});
Basicly, I need myFunction() to run every time anything changes in resources. I can't find any way to do this. I've tried looking into autoRun, along with cursor.dependency, but I don't really understand how they work, or how to apply them here. Any help would be greatly appreciated! Thanks!
You can try using cursor.observeChanges on the resources collection.
function myFunction(id, fields){
console.log("something happened on resources", id);
}
var cursor = resources.find();
cursor.observeChanges({
added:myFunction,
changed:myFunction,
removed:myFunction
});
https://docs.meteor.com/#/full/observe_changes
I have a template that looks like this:
<p ng-repeat="item in myobj.items" class="toAnimate">{{item}}</p>
and I would like to use the animate module do a jQueryUI addClass/removeClass animation on the element using the JavaScript method described in the docs:
ngModule.animation('.toAnimate', function() {
return {
enter: function(element) {
element.addClass('pulse').removeClass('pulse', 2000);
}
};
});
This works beautifully, but the problem is that, since I want to use the p.toAnimate element to display status messages, it will not change the content according to angular.
To break it down a little further, say I have a name field. When I click Save the message Name was saved successfully. is displayed. Now if I modify the name and click save again, assuming the save was successful, the message should be re-displayed to give the user feedback of the newly edited name. The pulse does not happen, however, because the items in myobj.items didn't technically change.
I realize that I could remove the item after a period of time (and that is probably the route I will take to implement the real solution), but I'm still interested to see if this sort of thing can be done using AngularJS.
What I want to do is register with angular that the message should be treated as new even though it is not. Is there any way to do this?
A fiddle to go along with this: http://jsfiddle.net/Jw3AT/
UPDATE
There is a problem with the $scope.$$phase approach in my answer, so I'm still looking for the "right" way to do this. Basically, $scope.$$phase is always returning $digest, which causes the conditional to fail. Removing the conditional gives the correct result in the interface, but throws a $rootScope:inprog.
One solution I found is to add a $apply in the middle of the controller function:
$scope.updateThingy = function () {
$scope.myobj.items = [];
if (!$scope.$$phase) {
$scope.$apply();
}
$scope.myobj.items = ['Your name was updated.'];
};
Updated fiddle: http://jsfiddle.net/744Rv/
May not be the best way, but it's an answer.
I didn't know a better way to phrase that question. I've written a basic service to be used by two controllers.
JsFiddle: http://jsfiddle.net/aditya/2Nd8u/2/
Clicking 'notify' works as expected; it adds a notification to the array. But 'reset' breaks it. Clicking either button after 'reset' doesn't do anything. Does anyone know what's going on here?
PS. I think it has something to do with Angular losing the reference since notifs is being re-assigned (technically), so I wrote getters and setters, but even emptying the array involves pop()ing till it's empty, which doesn't seem very efficient.
Plunkr if JsFiddle is down: http://plnkr.co/edit/mzfLLjFXCwsxM5KDebhc
I've forked your plunker and propose a solution:
In reset function, try to remove the objects of the array instead of declaring as new empty array:
notificationService.notifs.splice(0, notificationService.notifs.length);
Or, like suggested by #Wizcover:
notificationService.notifs.length = 0
This will notify angular that are modifications in the original array.
I changed your service to this:
.factory("notificationService", function(){
var notifications = [];
return {
notifs: notifications,
clear: function(){
angular.copy([], notifications);
},
get: function(){
return notifs;
}
}
})
and your controller :
$scope.reset = function(){
console.log("reset");
notificationService.clear();
console.log(notificationService);
}
and it works for me.
Naturally it should be a little bit tidier, in that instead of notifs you should have a get, and add and a remove method, but i just wanted to show you where the code changed.
The angular.copy is the method that makes sure the changes are made within angular's lifecycle.
As you can't bind variable but only methods, you could do this:
$scope.getNotifications = notificationService.get;
That should work.
This may sound really like a newbie .. But i used the jQuery Boilerplate on this page - http://stefangabos.ro/jquery/jquery-plugin-boilerplate-revisited/ and created a plugin. Everything works fine, except now i want to add a callback. I want to execute this -
$.Alerter({'message':'this is a test','onSuccess':function(data) { alert(data); } });
The onSuccess is a callback function which is added to the defaults.
My question is – how do i send the output to the onSuccess. I want it to return back a TRUE or FALSE value after certain steps have been executed in the init()
Something like this:
plugin.result = null;
plugin.init = function() {
// do stuff
...
// save _result in public variable result
plugin.result = _result;
}
If you are writing this plugin for dom operations, you could also use it like plugin.data('result',_result);
Since I don't know anything else I can't give further insight.
Hope this will help you.
We have a thick client app using jQuery heavily and want to profile the performance of the code using firebug's console.profile API. The problem is, I don't want to change the code to write the profile statements. Take this example:
var search=function(){
this.init=function(){
console.log('init');
}
this.ajax=function(){
console.log('ajax');
//make ajax call using $.ajax and do some DOM manipulations here..
}
this.cache=function(){
console.log('cache');
}
}
var instance=new search();
instance.ajax();
I want to profile my instance.ajax method, but I dont want to add profile statements in the code, as that makes it difficult to maintain the code.
I'm trying to override the methods using closures, like this: http://www.novogeek.com/post/2010/02/27/Overriding-jQueryJavaScript-functions-using-closures.aspx but am not very sure how I can achieve. Any pointers on this? I think this would help many big projects to profile the code easily without a big change in code.
Here is the idea. Just run the below code in firebug console, to know what I'm trying to achieve.
var search=function(){
this.init=function(){
console.log('init');
}
this.ajax=function(){
console.log('ajax');
//make ajax call using $.ajax and do some DOM manipulations here..
}
this.cache=function(){
console.log('cache');
}
}
var instance=new search();
$.each(instance, function(functionName, functionBody){
(function(){
var dup=functionBody
functionBody=function(){
console.log('modifying the old function: ',functionName);
console.profile(functionName);
dup.apply(this,arguments);
console.profileEnd(functionName);
}
})();
console.log(functionName, '::', functionBody());
});
Now what I need is, if i say instance.ajax(), I want the new ajax() method to be called, along with the console.profile statements. Hope I'm clear with the requirement. Please improvise the above code.
Regards,
Krishna,
http://www.novogeek.com
If you only want to modify the single instance of "search" then this should work:
$.each(instance, function(name, method){
if (typeof method !== 'function') return;
instance[name] = function() {
console.profile(name);
var ret = method.apply(this, arguments);
console.profileEnd(name);
return ret;
};
});
I know this is from a long time ago but I wanted to add this in case other people find this answer. You can make anonymous/private functions work by adding a name to each one. The other comments mention doing it manually bit I wanted to explain how to:
$('.stuff').each(function() { ... });
to
$('.stuff').each(function workOnStuff() { ... });