I am trying to add a delay of 2000ms by using the timeout method but it is not working if I try to call it in the function(searchfunc) inside the cotroller. It gives Error: $timeout is not a function .
Controller code :
var angularjsapp = angular.module('graphApp', ['ngAnimate', 'ui.bootstrap','ui.grid']);
angularjsapp.controller('AccordionDemoCtrl', function($scope, $timeout) {
$scope.searchfunc = function(search_name,$timeout) {
WebSocketTest(search_name,keyword_type);
//$scope.loading = false;
$timeout(function () {
$scope.loading = false;
}, 2000);
});
You're passing $timeout as a parameter to your function
$scope.searchfunc = function(search_name,*$timeout*
which will make it undefined when you call the function because you don't pass it along. Removing it will fix the issue.
scope.searchfunc = function(search_name)
You can read about how this works (closures) here
You override $timeout in the inner function.
Just omit it:
$scope.searchfunc = function(search_name) {
May be you mean second parameter to be keyword_type?
Because now it's looks like undefined.
$scope.searchfunc = function(search_name, keyword_type) {
Related
I am writing my first AngularJS app and I'm trying to get a directive to update its view when an array it received from the service changed.
My directive looks like this:
angular.module('Aristotle').directive('ariNotificationCenter', function (Notifications) {
return {
replace: true,
restrict: 'E',
templateUrl: 'partials/ariNotificationCenter.html',
controller: function ($scope) {
$scope.notifications = Notifications.getNotifications();
$scope.countUnread = function () {
return Notifications.countUnread();
};
}
};
});
The partial is quite simply:
<p>Unread count: {{countUnread()}}</p>
While my Notifications service looks like this:
function Notification (text, link) {
this.text = text;
this.link = link;
this.read = false;
}
var Notifications = {
_notifications: [],
getNotifications: function () {
return this._notifications;
},
countUnread: function () {
var unreadCount = 0;
$.each(this._notifications, function (i, notification) {
!notification.read && ++unreadCount;
});
return unreadCount;
},
addNotification: function (notification) {
this._notifications.push(notification);
}
};
// Simulate notifications being periodically added
setInterval(function () {
Notifications.addNotification(new Notification(
'Something happened!',
'/#/somewhere',
Math.random() > 0.5
));
}, 2000);
angular.module('Aristotle').factory('Notifications', function () {
return Notifications;
});
The getNotifications function returns a reference to the array, which gets changed by the setInterval setup when addNotification is called. However, the only way to get the view to update is to run $scope.$apply(), which stinks because that removes all the automagical aspect of Angular.
What am I doing wrong?
Thanks.
I believe the only problem with you code is that you are using setInterval to update the model data, instead of Angular built-in service $interval. Replace the call to setInterval with
$interval(function () {
Notifications.addNotification(new Notification(
'Something happened!',
'/#/somewhere',
Math.random() > 0.5
));
}, 2000);
And it should work without you calling $scope.$apply. Also remember to inject the $interval service in your factory implementation Notifications.
angular.module('Aristotle').factory('Notifications', function ($interval) {
$interval internally calls $scope.$apply.
I'm not an expert at Angular yet, but it looks like your problem may be in the partial.
<p>Unread count: {{countUnread()}}</p>
I don't think you can bind to a function's results. If this works, I believe it will only calculate the value once, and then it's finished, which appears to be the issue you are writing about.
Instead, I believe you should make a variable by the same name:
$scope.countUnread = 0;
And then update the value in the controller with the function.
Then, in your partial, remove the parentheses.
<p>Unread count: {{countUnread}}</p>
As long as $scope.countUnread is indeed updated in the controller, the changes should be reflected in the partial.
And as a side note, if you take this approach, I'd recommend renaming either the variable or the function, as that may cause issues, or confusion at the very least.
I want to capture the url of my query in an AngularJS service as this
var mortgageloanService = angular.module('loanstreetIpadAppApp', []);
mortgageloanService.factory('updateTable', function($http) {
return {
getParams: function() {
var url = 'https://api.mongolab.com/api/1/databases/angularjs-intro/collections/users?apiKey=terrPcifZzn01_ImGsFOIZ96SwvSXgN9';
console.log('in service mode');
console.log(url);
return $http.get(url);
}
};
});
This is my controller.js code
angular.module('loanstreetIpadAppApp')
.controller('Mortgage_LoanCtrl', function ($location, $scope) {
$scope.update_result = function(updateTable) {
updateTable.getParams().success(function(loan){$scope.loan = loan});
console.log($scope.resulttable);
};
});
On my view page, i have a button which onclick shud call the update_result function. But whenever i click on the button i get the following error
TypeError: Cannot read property 'getParams' of undefined
at Scope.$scope.update_result (http://localhost:9003/scripts/controllers/mortgage_loan.js:22:16)
at http://localhost:9003/bower_components/angular/angular.js:10567:21
at http://localhost:9003/bower_components/angular/angular.js:18627:17
at Scope.$eval (http://localhost:9003/bower_components/angular/angular.js:12412:28)
at Scope.$apply (http://localhost:9003/bower_components/angular/angular.js:12510:23)
at HTMLButtonElement.<anonymous> (http://localhost:9003/bower_components/angular/angular.js:18626:21)
at HTMLButtonElement.jQuery.event.dispatch (http://localhost:9003/bower_components/jquery/dist/jquery.js:4430:9)
at HTMLButtonElement.elemData.handle (http://localhost:9003/bower_components/jquery/dist/jquery.js:4116:28)
Anyone knows how to solve this issue?
In order to use your updateTable's factory inside your controller, you need to inject it. So, your controller should look like this.
angular.module('loanstreetIpadAppApp')
.controller('Mortgage_LoanCtrl', function ($location, $scope, updateTable) {
$scope.update_result = function() {
updateTable.getParams().success(function(loan){$scope.loan = loan});
console.log($scope.resulttable);
};
});
Notice that I've removed "updateTable" as "$scope.update_result"'s parameter since it would overwrite your updateTable object inside that closure.
In my controller, I have:
var timespanServiceFn;
timespanServiceFn = function() {
return timespanService.getTimespan();
};
$scope.$watch(timespanServiceFn, $scope.updateVolume());
My $scope.updateVolume() function just has a console.log so that I know I got there.
My timespanService is also super simple:
myApp.service('timespanService', [
'$http', '$q', function($http, $q) {
var currentTimespan;
currentTimespan = '3M';
this.getTimespan = function() {
return currentTimespan;
};
this.setTimespan = function(timespan) {
console.log('setting timespan to', timespan);
return currentTimespan = timespan;
};
}
]);
So why is it that when I changed the timespan, the $watch doesn't get triggered?
The watch takes two functions as arguments. You must pass the second parameter as argument but you just called it there:
$scope.$watch(timespanServiceFn, $scope.updateVolume());
so the return statement of $scope.updateVolume() will be passed to $watch function instead of the function definition itself.
Just change it to:
$scope.$watch(timespanServiceFn, $scope.updateVolume);
See demo
Using the facebook api, you can add a listener that triggers a function whenever someone clicks a like button:
FB.Event.subscribe('edge.create', page_like_callback);
This is what my function looks like, where I listen:
function($scope, $window) {
$scope.liking = $window.liking;
FB.Event.subscribe('edge.create', page_like_callback);
}
I want to set $scope.liking = true; for whenever someone clicks like:
var page_like_callback = function(url, html_element) {
$scope.liking = true;
};
But the $scope variable isn't accessible inside the callback. I either want to pass $scope to the callback or get a return from the callback and use that to set the like. What's the best approach for this and how should I do it?
You could have a function return your callback taking $scope as an argument so that $scope is now captured by the callback function
var page_like_callback = function($scope) {
return function(url, html_element) {
$scope.liking = true;
};
}
FB.Event.subscribe('edge.create', page_like_callback($scope));
That's because the $scope variable is only defined within your function($scope, $window), so you need to make sure that page_like_callback has access to it. One way to do this is:
function($scope, $window) {
var page_like_callback = function(url, html_element) {
$scope.liking = true;
};
$scope.liking = $window.liking;
FB.Event.subscribe('edge.create', page_like_callback);
}
That way, page_like_scope has access to $scope.
This is a bit spaghetti-ish, so you might need to provide more of your code if you want a better solution.
This is my controller:
function TestCtrl ($scope, sharedProperties, $resource){
var userDataProfile = sharedProperties.getUserDataProfile();
var userCreatedBoard = $resource('/boards?owner=:owner');
userCreatedBoard.query({'owner':userDataProfile.id}, function (result) {
console.log(result);
});
}
Now problem is sharedProperties.setUserDataProfile() is called after calling a 3rd party service and its async. Hence, when the TestCtrl is bound, userDataProfile is effectively null. How do I handle this situation so that after the sharedProperties.setUserDataProfile() is called and variable has been assigned a value from 3rd party service, then only my controller should get bound?
I think you want to look at resolve:
http://www.youtube.com/watch?v=Kr1qZ8Ik9G8
This allows you to load all your data before instantiating your controller and firing a routeChangeSuccess event.
In the angular docs.
It does not make sense to pass variables into an Angular.js controller like that, that is what the Scope variable is meant for.
Try this
window.activeTestCtrls = [];
window.sharedProperties = [];
function TestCtrl ($scope, $resource){
if (window.sharedProperties) this.createUserData(window.sharedProperties)
window.activeTestCtrls.push[this];
function createUserData(sharedProperties) {
var userDataProfile = sharedProperties.getUserDataProfile();
var userCreatedBoard = $resource('/boards?owner=:owner');
userCreatedBoard.query({'owner':userDataProfile.id}, function (result) {
console.log(result);
}
});
// and when you get your sharedproperties
function gotSharedProperties(sharedProperties) {
$.each(activeTestControllers, function(index,value) {
activeTestControllers[index].createUserData(sharedProperties)})
}
}