我有以下两个指令。在DirectiveA
中,我从远程服务器获取一些数据,然后将包含该数据的模板呈现为anchor
标记。现在,当用户点击任意链接时,我broadcast
会在DirectiveB
中收听该事件。在DirectiveB中,我想制作另一个ajax请求,当我收到数据响应时,我想渲染DirectiveB
模板。我当前的方法不起作用,因为它在开始时执行两个指令,那时我没有DirectiveB
的任何数据。以下是代码
DirectiveA
angular.module('app').directive('DirectiveA', function ($http) {
'use strict';
return {
restrict: 'E',
templateUrl: '/templates/templateA.html',
controller: function ($scope) {
$scope.showDetails = function (num) { // <-- this executes in ng-click in template
$scope.$broadcast('season', num);
};
},
link: function (scope, element, attributes) {
$http.get(attributes.resource).then(function (response) {
scope.rows = response.data;
scope.seasons = [];
for (var i = 0; i < scope.rows.length; i++) {
var num = parseInt(scope.rows[i].data);
if (year >= 2005 && year <= 2015) {
scope.seasons.push({ 'data': scope.rows[i].data });
}
}
});
}
};
});
这是DirectiveB
angular.module('app').directive('DirectiveB', function() {
return {
restrict: 'E',
templateUrl: 'templates/templateB.html',
controller: function($scope, $http) {
$scope.$on('season', function ($scope, num) { // I listen to that event
$http.get('http://demo.com/api/' + num).then(function (response) {
$scope.standings = response.data;
});
});
}
};
});
更新
以下是我在HTML中使用它的方法
<directive-a resource="http://demo.com/api/>
</directive-a>
<directive-b></directive-b>
更新
我还在等待解决方案。
更新3
templateA
<ul>
<li ng-repeat="row in seasons">
<a href="#" ng-click="showDetails(row.season)">{{ row.season }}</a>
</li>
</ul>
模板B
<h3>Standings</h3>
<table>
<thead>
<th ng-repeat="standing in standings" ng-if="state">{{ position }}</th>
</thead>
<tbody>
<tr ng-repeat="row in standings">
{{ row.Driver }}
</tr>
</tbody>
</table>
答案 0 :(得分:4)
您的问题归结为:
如何确保DirectiveA
和DirectiveB
由于您的指令使用相同的范围,因此您的事件广播解决方案可行。将DDO内的scope
设置更改为false
以外的任何内容时,这会中断。
这就是为什么我会$broadcast
在$rootScope
为您提供DirectiveB
活动的原因。
数据准备好后如何呈现ngIf
的模板
包装指令模板的简单$rootScope.$broadcast
可以完成这项工作。我们不需要任何花哨的东西。
贝娄是一个简单的工作示例。请注意两个指令如何使用隔离范围 - 这只是为了展示您需要$timeout
的原因。我也使用angular
.module('myApp', [])
.directive('directiveA', function() {
return {
templateUrl: 'tempA.html',
controller: function($rootScope, $scope) {
$scope.sendMessage = function(message) {
$rootScope.$broadcast('eventName', message);
};
},
scope: {}
};
})
.directive('directiveB', function() {
return {
templateUrl: 'tempB.html',
controller: function($rootScope, $scope, $timeout) {
$scope.messages = [];
$rootScope.$on('eventName', function(event, message) {
$timeout(function() {
$scope.messages.push(message);
}, 50);
});
},
scope: {}
};
});
来模拟服务器的延迟。
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="myApp">
<directive-a></directive-a>
<directive-b></directive-b>
<script type="text/ng-template" id="tempA.html">
<h2>Hello from DirectiveA</h2>
<label>
<p>Message to send to DirectiveB</p>
<input type="text" ng-model="toSend">
</label>
<button type="button" ng-click="sendMessage(toSend); toSend = '';">Send</button>
</script>
<script type="text/ng-template" id="tempB.html">
<div ng-if="messages.length > 0">
<h3>Hello from DirectiveB</h3>
<ul>
<li ng-repeat="message in messages track by $index">{{ message }}</li>
</ul>
</div>
</script>
</div>
$sql = "SELECT * FROM tablename WHERE condition";
$res = mysql_query($sql);
while ($row = mysql_fetch_assoc($res)) {
foreach($row as $key => $field) {
echo "<br>";
if(empty($row[$key])){
echo $key." : empty field :"."<br>";
}else{
echo $key." =" . $field."<br>";
}
}
}
答案 1 :(得分:2)
使用API(角度服务)在您的指令之间进行通信。在我的例子中,我称之为MyAPIService:
angular.module('app').service('MyAPIService', function () {
this.display = false;
this.seasons = [];
});
然后在两个指令和指令A中注入API的实例,当你点击你的锚点时,你必须填充你的季节并更新你的“显示”变量。在你的directiveB上,只需看“显示”变量
angular.module('app').directive('DirectiveA', function ($http, MyAPIService) {
'use strict';
return {
restrict: 'E',
templateUrl: '/templates/templateA.html',
controller: function ($scope) {
$scope.showDetails = function () {
MyAPIService.display = true;
},
link: function (scope, element, attributes) {
$http.get(attributes.resource).then(function (response) {
scope.rows = response.data;
MyAPIService.seasons = [];
for (var i = 0; i < scope.rows.length; i++) {
var num = parseInt(scope.rows[i].data);
if (year >= 2005 && year <= 2015) {
MyAPIService.seasons.push({ 'data': scope.rows[i].data });
}
}
});
}
};
});
angular.module('app').directive('DirectiveB', function() {
return {
restrict: 'E',
templateUrl: 'templates/templateB.html',
controller: function($scope, $http, MyAPIService) {
// WATCH "DISPLAY" VARIABLE AND CALL YOUR AJAX
}
};
});
答案 2 :(得分:1)
我为您提供了一个有效的解决方案,与您的广播方式略有不同。正如您所提到的,您只想在单击指令A之后加载指令B的数据。因此,我们将放置一个条件来从DOM中删除指令B.当指令A的点击触发时,我们将在DOM中加载指令B。这样你的指令B的控制器将在稍后加载。
以下是支持我的论点的代码
指令A
angular.module('app').directive('DirectiveA', function ($http) {
'use strict';
return {
restrict: 'E',
templateUrl: '/templates/templateA.html',
controller: function ($scope) {
$scope.showDetails = function (num) { // <-- this executes in ng-click in template
$scope.isDirectiveBVisible = true;
};
},
link: function (scope, element, attributes) {
$http.get(attributes.resource).then(function (response) {
scope.rows = response.data;
scope.seasons = [];
for (var i = 0; i < scope.rows.length; i++) {
var num = parseInt(scope.rows[i].data);
if (year >= 2005 && year <= 2015) {
scope.seasons.push({ 'data': scope.rows[i].data });
}
}
});
}
};
});
指令B
angular.module('app').directive('DirectiveB', function() {
return {
restrict: 'E',
templateUrl: 'templates/templateB.html',
controller: function($scope, $http) {
$http.get('http://demo.com/api/' + num).then(function (response) {
$scope.data = response.data;
});
}
};
});
HTML
<directive-a resource="http://demo.com/api/>
</directive-a>
<directive-b ng-if="isDirectiveBVisible"></directive-b>
答案 3 :(得分:1)
很久以前我创建了this solution就像实验一样
<div ng-directive="{{directive}}"></div>
您可以在其中动态呈现指令。
但你问的不是动态渲染。 关于改变组件状态(指令)。
您已经提供了关于使用ngIf
的答案,事情只是在哪里放置它。我建议将它放在你的指令中并为整个模板制作包装器:
<div ng-if="isShown">
<h3>Standings</h3>
...
</div>
并将isShown
范围属性设置在您需要的位置,例如在事件之后:
$scope.$on('season', function ($scope, num) {
$scope.isShown = true;
});
或在ajax电话之后:
$http.get('http://demo.com/api/' + num).then(function (response) {
$scope.isShown = true;
});
此外,我建议不仅要播放能见度,还要使用加载指示来表示它的加载效果:
<div ng-if="isShown">
<loading-indicator ng-if="isLoading">
<div ng-if="!isLoading">
<h3>Standings</h3>
...
</div>
</div>
答案 4 :(得分:0)
您可以尝试在指令A中使用ng-if和某种标志来指示ajax请求已完成。 ng-if将隐藏元素包装在注释中,这样它们就不会出现在dom中,直到条件为真。
答案 5 :(得分:0)
来自"AngularJs $scope documentation"
将事件名称向下调度到所有子范围(及其子级),通知已注册的$ rootScope.Scope侦听器。
这意味着你的directiveB必须是你的directiveA的子代,才能捕获广播事件。例如:
<directive-A>
<directive-B></directive-B>
</directive-A>
指令的控制器功能代码将在html渲染之前执行,链接的功能代码将在html渲染之后执行。这意味着您无法处理directiveB的执行。当您从directiveA中进行的调用得到响应时,可以简单地创建它。例如:
scope.data={resolved:false};
$http.get(attributes.resource).then(function (response) {
scope.rows = response.data;
scope.seasons = [];
scope.data.resolved = true;
for (var i = 0; i < scope.rows.length; i++) {
var num = parseInt(scope.rows[i].data);
if (year >= 2005 && year <= 2015) {
scope.seasons.push({ 'data': scope.rows[i].data });
}
}
});
在上面的HTML示例中:
<directive-A>
<directive-B ng-if="data.resolved"></directive-B>
</directive-A>
通过这种方式,您的protocolB将在您的呼叫解决后创建。
注意但是:如果您使用ngIf,您可能会丢失$ broadcast事件,因为您的directiveB&#39; $ on将在$ broadcast
之后创建答案 6 :(得分:0)
我认为最好的解决方案,如果你想保留两个指令,就是在你的指令B模板中使用ng-if
指令,只有在有结果时才显示表格
您只需修改指令B模板以向当前表格添加条件,并添加<div>
或类似内容,以便在用户尚未选择任何项目时显示消息。< / p>
您的指令B模板类似于:
<h3>Standings</h3>
<!-- Add ng-if here -->
<table ng-if="standings.length > 0">
<thead>
<th ng-repeat="standing in standings" ng-if="state">{{ position }}</th>
</thead>
<tbody>
<tr ng-repeat="row in standings">
{{ row.Driver }}
</tr>
</tbody>
</table>
<!-- and also here -->
<!-- If standings is not an array -->
<div ng-if="!standings.length">
<p>Please, select one of the items above to show standings.</p>
</div>
您可以根据需要添加尽可能多的div。例如,您可以在所选项目没有结果时添加消息:
<!-- If standings is an array but it is empty -->
<div ng-if="standings.length && standings.length > 0">
<p>There are no standings to show.</p>
</div>