问题
In my Directive, I've getting some data from my backend like this:
var monster_info = angular.element(this).find("img").attr("title");
$http.get("lib/terrain.php", {params: { monster_data:monster_info}}).success(function(data) {
console.log(data);
});
I want this data to appear at my site, so I've tried to declare a variable like this in my controller: $scope.fish = [];
Then I just assign the data value like this in my directive: $scope.fish = data;
But nothing is printed out. How does the communication between controller and directive work? How should I share this kind of data?
Here is my whole directive:
angular.module('gameApp_directives').
directive('mapActivity', function($http) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch('tabledata', function() {
angular.element('.click#1').addClass('dotted').html($("<img src='images/dot.png'>"));
var j = null;
for(var i = 1; i <= 4; i++)
{
$.ajax({
type: 'GET',
url: 'lib/terrain.php',
dataType: 'html',
data: {i: i},
success: function(data) {
var randomRuta = Math.floor((Math.random() * 100) + 1);
angular.element('.click#'+randomRuta).addClass('monster').html($("<img src='images/blackdot.png' title='"+data+"'>"));
},
error: function(xhr, ajaxOptions, thrownError) { alert(thrownError); }
});
j=i;
}
angular.element('.click').click(function() {
if(angular.element(this).hasClass('monster'))
{
var monster_info = angular.element(this).find("img").attr("title");
$http.get("lib/terrain.php", {params: { monster_data:monster_info}}).success(function(data) {
console.log(data);
});
/*if(confirm('Vill du anfalla monster?'))
{
alert("Du vann");
angular.element('.click.monster'+j).empty();
angular.element('.click.monster').removeClass('monster'+j);
angular.element('.click.dotted').empty();
angular.element('.click.dotted').removeClass('dotted');
angular.element(this).addClass('dotted');
angular.element('.click.dotted').html($('<img src="images/dot.png">'));
}*/
}
else
{
angular.element('.click.dotted').empty();
angular.element('.click.dotted').removeClass('dotted');
if(!angular.element(this).hasClass('dotted'))
{
angular.element(this).addClass('dotted');
angular.element(this).html($('<img src="images/dot.png">'));
}
}
});
});
}
};
});
Here is my controller:
angular.module('gameApp_controllers')
.controller('gameCtrl', ['$scope', '$http', '$location', '$sce', '$rootScope', 'link', function($scope, $http, $location, $sce, $rootScope, link) {
$scope.resultLoaded = false;
$scope.getMonsters = "1";
var tabledata = ""; //Variable to store pattern for html table
$http.post("lib/action.php", {monsters: $scope.getMonsters}).success(function(data) {
//tabledata = data; //Assign the pattern
$scope.result = makeTableFrom(data); //Call the function to build the table based on the pattern
$scope.resultLoaded = true;
}).error(function(data) { console.log("error"); });
$scope.fish = [];
$scope.safeHtml = function() {
return $sce.trustAsHtml($scope.result);
};
if(link.user) {
/*$scope.message = "fisk";
console.log(link.user);*/
} else {
/*$scope.message = "Ledsen fisk";
console.log("Är inte satt");*/
}
}]).controller('firstPageCtrl', ['$scope','$http','$location','$sce','$rootScope','link', function($scope, $http, $location, $sce, $rootScope, link) {
$scope.doLogin = function() {
$http.post("lib/action.php", {username: $scope.username, password: $scope.password}).success(function(data) {
if(data) {
link.user = data;
console.log(link.user);
$location.path("/game");
}
}).error(function(data) {
console.log(data);
});
};
}]);
Anyone who can help me?
Here is my HTML
<div id="layout_game">
<div ng-controller="gameCtrl">
<div ng-if='resultLoaded' id="rightcontent_game">
<table ng-bind-html="safeHtml()" map-Activity>
</table>
</div>
<div id="leftcontent_game">
<div id="leftcontent_top">
<ul>
<li><a href="#">Vildmarken</a></li> <li> | </li> <li><a href="#">Marknaden</a></li> <li> | </li> <li><a href="#">Värdshuset</a></li>
</ul>
</div>
{{fish}}
</div>
</div>
</div>
回答1:
I would just broadcast an event from the directive like this:
$rootScope.$broadcast('fishChange', fishValue);
And then in the controller listen for that event:
$scope.$on('fishChange', function(event, fishValue) {
// Do whatever you want here
});
回答2:
Communication between a directive and its parent controller can work in a few different ways, depending on how you define the scope
property in your directive definition object.
The default is scope: false
, which is what you are implicitly using in your example above of the mapActivity
directive, since you did not specify one. (for the other modes, see the docs on $compile, under the "scope" setting)
This means no new scope is created - the directive will have direct access to the containing controller's $scope via the scope
argument you pass as the first parameter of the link function.
Your code might not have worked for the simple reason that you wrote $scope.fish = data
in your directive, rather than scope.fish = data
(without the dollar sign). Actually, looking at the directive code you posted, you don't try to assign to a fish
property anywhere. Perhaps you just ommitted it in the example?
re: using '$rootScope.$broadcast()'
I would personally recommend against using the $rootScope.broadcast()
method as suggested by lulu88. I would reserve broadcasting onto the $rootScope to only those circumstances where there is no simple, direct means on communication between two components. In this case, as I explained, there is a very simple means.
From the Angular docs
$broadcast(name, args);
Dispatches an event name downwards to all child scopes (and their children) notifying the registered $rootScope.Scope listeners.
The event life cycle starts at the scope on which $broadcast was called. All listeners listening for name event on this scope get notified. Afterwards, the event propagates to all direct and indirect scopes of the current scope and calls all registered listeners along the way. The event cannot be canceled.
So if you call $broadcast() on the $rootScope, you will be propagating the event to every scope in your app. This is unnecessary for anything but global app-wide events - a typical one being user logging in or out.
回答3:
You may know that "input" or "select" HTML component can report their state to controller by using ng-model. In fact we can also make our own directive support the same feature.
The process can be digested as:
- Add "require: 'ngModel'" to directive's js, letting ng-model available in template html.
- Use ngModelCtrl.$formatters method to convert model value into view value.
- Use ngModelCtrl.$render method to update the UI to reflect view value.
- Use ngModelCtrl.$parsers method to convert view value into model value.
- Use ngModelCtrl.$setViewValue method to update view value when the UI changes.
Visualising the full circle
<realModel> → ngModelCtrl.$formatters(realModel) → $viewModel ↓ ↑ $render() ↓ ↑ UI changed ↓ ngModelCtrl.$parsers(newViewModel) ← $setViewValue(newViewModel)
The full version tutorial
来源:https://stackoverflow.com/questions/25505116/get-value-from-directive-to-scope-in-controller