Ok.. I've tried angular.js. It is awesome. I'm impressed. I can get bindings and stuff.. Cool.
Now what if I need to access to my data from outside of the $scope? Let's say I have a signalR hub that sends some data and function that intercepts that and should add a new item or modify existing. How do I do that? Can you show me on this example how can I access $scope.twitterResult
from click
handle?
<script>
angular.module('Twitter', ['ngResource'])
function TwitterCtrl($scope, $resource){
$scope.twitter = $resource('http://search.twitter.com/:action',
{action: 'search.json', q: 'obama', callback:'JSON_CALLBACK'},
{get:{method:'JSONP'}});
$scope.doSearch = function(){
$scope.twitterResult = $scope.twitter.get();
}
}
$(function(){
$('#addItem').click(function(){
// add a row to $scope.twitterResult
});
});
</script>
<body>
<div data-loading></div>
<div ng-controller='TwitterCtrl' ng-init="doSearch()">
<ul>
<li ng-repeat='tweet in twitterResult.results'><p> {{tweet.text}}</p></li>
</ul>
</div>
</body>
A better way would be to wrap your "signal hub" in an AngularJS service. Take a look on my blog post about using web sockets with AngularJS, specifically "Interacting with Socket.IO."
Why did you write:
$(function(){
$('#addItem').click(function(){
// add a row to $scope.twitterResult
});
});
And not just use ng-click
? Is this some 3rd party code or widget? Pending on these this, I'll try to better advise you and write up some example code.
If you have to register an event handler, you should do so through a directive. Otherwise things will get complicated when you start managing the lifecycles of these outside-of-angular event bindings.
General answer is: you don't simply mess with the scopes from the outside.
But the requirement you have is a genuine one.
So in order to do what you want you need to establish a communication between outside of the scope and the scope itself.
The easiest way is to export the $scope to window and just mess with it, breaching into the scope from outside. You should NEVER do this. There be dragons.
The scope should maintain it's internal state.
I'm not exactly familiar with angular
but you can do something to the effect of:
function TwitterCtrl($scope, $resource) {
// ...
$('body').bind('newTweetsArrived', data) {
// data contains the new tweets
// the decision to accept or not new tweets is made within the control
if (in_the_mood_to_accept_new_tweets) {
// add new tweets to the $scope.twitterResult
}
// optionally notify other components that new tweets are accepted
// so that they can adjust or whatever
$('body').trigger('afterNewTweetsArrived');
}
}
// you add new tweets by triggering global custom event
$(function(){
$('#addItem').click(function(){
$('body').trigger('newTweetsArrived', { ...here_are_the_tweets... });
});
});
You could probably do something like this, but I'm not sure if it's the best idea:
var myTwitterScope;
angular.module('Twitter', ['ngResource'])
function TwitterCtrl($scope, $resource){
$scope.twitter = $resource('http://search.twitter.com/:action',
{action: 'search.json', q: 'obama', callback:'JSON_CALLBACK'},
{get:{method:'JSONP'}});
$scope.doSearch = function(){
myTwitterScope = $scope;
$scope.twitterResult = $scope.twitter.get();
}
}
$(function(){
$('#addItem').click(function(){
// add a row to $scope.twitterResult
myTwitterScope.twitterResult.push(...); // or however you would do this.
});
});
As others have mentioned, this is not the cleanest solution.