我正在创建一个Angular tabs指令,该指令将按如下方式应用:
<div id="tabs-with-directive" data-tabs>
<ul class="tabs">
<li><a href="#" data-tabs-link="1">One</a></li>
<li><a href="#" data-tabs-link="2">Two</a></li>
</ul>
<div class="panes">
<div data-tabs-pane="1" class="pane active">One</div>
<div data-tabs-pane="2" class="pane">Two</div>
</div>
</div>
因此,单击One将显示第一个窗格,其中两个将显示第二个窗格,...
我创建了一个有效的Plunker example without using a directive
我有Plunker example using the directive I am trying to build:
angular.module("app", [tabs]);
(function(angular) {
'use strict';
angular.module('tabs', []);
angular.module('tabs')
.directive('tabs', tabsDirective);
function tabsDirective() {
return {
scope: true,
restrict: 'A',
controller: tabsController
};
}
function tabsController($scope) {
$scope.tabs = [];
this.addTab = function (tab) {
$scope.tabs.push(tab);
};
this.isTabActive = function (link) {
for(var i = 0; i < $scope.tabs.length; i++) {
if ($scope.tabs[i].link == link)
return $scope.tabs[i].active;
}
return false;
};
this.setTabToActive = function (link) {
for(var i = 0; i < $scope.tabs.length; i++)
$scope.tabs[i].active = $scope.tabs[i].link == link;
};
}
tabsController.$inject = ['$scope'];
angular.module('tabs')
.directive('tabsLink', tabsLinkDirective);
function tabsLinkDirective() {
return {
scope: false,
restrict: 'A',
require: '^tabs',
link: function (scope, element, attributes, controller) {
var tab = { link: attributes.link, active: "false" };
controller.addTab(tab);
element.bind('click', function () {
controller.setTabToActive(attributes.link);
});
scope.$watch('tabs', function () {
element.toggleClass('active', controller.isTabActive(attributes.link));
});
}
};
}
angular.module('tabs')
.directive('tabsPane', tabsPaneDirective);
function tabsPaneDirective() {
return {
scope: false,
restrict: 'A',
require: '^tabs',
link: function (scope, element, attributes, controller) {
scope.$watch('tabs', function () {
element.toggleClass('active', controller.isTabActive(attributes.pane));
});
}
};
}
})(angular);
不幸的是,这不起作用,我找不到我做错了什么。
有人可以帮帮我吗?
答案 0 :(得分:1)
默认情况下,$watch
会比较参考相等性。由于您正在修改数组中的对象,因此数组引用将保持不变,并且不会触发监视侦听器。
要监视对数组中对象的修改,您需要将true
作为第三个参数传递:
scope.$watch('tabs', function() {
element.toggleClass('active', controller.isTabActive(tab.link));
}, true);
以下内容:
attributes.link
在所有地方都应该替换为以下内容:
attributes.tabsLink
以下内容:
attributes.pane
应替换为:
attributes.tabsPane
我假设你希望其中一个标签开始处于活动状态。
以下您无法使用:
class="pane active"
由于没有任何标签模型将active
设置为true
,因此以下代码将剥离active
类:
scope.$watch('tabs', function() {
element.toggleClass('active', controller.isTabActive(attributes.tabsPane));
}, true);
如果您希望active
类指示选项卡是否应该以活动状态启动,您可以添加以下内容:
if (element.hasClass('active')) {
controller.setTabToActive(attributes.tabsPane);
}
请注意,这不会阻止多个标签作为活动标签启动,如果没有该标签,也不会将其设置为活动状态。
我强烈建议改变:
active: "false"
要:
active: false
而是使用严格的相等(===
代替==
)
element.on
不是AngularJS函数,不会为您触发摘要循环 - 这意味着数据绑定不会在UI中更新。
您需要手动执行此操作:
element.bind('click', function() {
scope.$apply(function() {
controller.setTabToActive(tab.link);
});
});