如果您对AngularJSTransclusionDirectivewithngRepeat导致混合范围感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于AngularJSTr
如果您对AngularJS Transclusion Directive with ngRepeat导致混合范围感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于AngularJS Transclusion Directive with ngRepeat导致混合范围的详细内容,并且为您提供关于AngualrJS中的Directive制作一个菜单_AngularJS、Angular 根据 service 的状态更新 directive_AngularJS、AngularJs Directive Pass value/object/function to Scope、angularjs directive semantic-ui pagination的有价值信息。
本文目录一览:- AngularJS Transclusion Directive with ngRepeat导致混合范围
- AngualrJS中的Directive制作一个菜单_AngularJS
- Angular 根据 service 的状态更新 directive_AngularJS
- AngularJs Directive Pass value/object/function to Scope
- angularjs directive semantic-ui pagination
AngularJS Transclusion Directive with ngRepeat导致混合范围
当我最终看到一个看似随机的结果时,我试图这样做. ngRepeat中的ngTransclude从指令的作用域返回值,而不是控制器的作用域.
关闭AngularJS文档,我创建了一个Plunker:http://plnkr.co/edit/GtrYtGoy2fnvgkwLFAGN?p=preview
JS
angular.module('docsTransclusionExample',[]) .controller('Controller',['$scope',function($scope) { $scope.names = ['Tobias','Funke']; }]) .directive('myDialog',function() { return { restrict: 'E',transclude: true,scope: {},templateUrl: 'my-dialog.html',link: function (scope,element) { scope.names = ['Jeff','Bridges']; } }; });
的index.html
<!doctype html> <html lang="en"> <head> <Meta charset="UTF-8"> <title>Example - example-example87-production</title> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script> <script src="script.js"></script> </head> <body ng-app="docsTransclusionExample"> <div ng-controller="Controller"> <my-dialog>Check out the contents,{{names}}!</my-dialog> </div> </body> </html>
我-dialog.html
<divng-transclude></div> <div ng-repeat="name in names"> <divng-transclude></div> {{name}} </div> <divng-transclude></div>
此代码返回:
Check out the contents,["Tobias","Funke"]! Check out the contents,["Jeff","Bridges"]! Jeff Check out the contents,"Bridges"]! Bridges Check out the contents,"Funke"]!
根据我读过的文档,以及我发现的用于翻译和范围的翻译和范围文章,翻译只应该考虑到控制器的范围,意思是中间的两个“查看内容,{{names}}!”应该读与外面两个相同.
进一步的实验让我将AngularJS版本从1.2.15更改为1.3.0 rc
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.1/angular.min.js"></script>
这导致正确的(据我所知)输出:
Check out the contents,"Funke"]! Jeff Check out the contents,"Funke"]! Bridges Check out the contents,"Funke"]!
有没有针对此问题的解决方法,我可以使用1.2.15或我在使用此版本时卡住了?应该是什么样的正确行为?
解决方法
ngRepeat: ensure that the correct (transcluded) scope is used
(b87e5fc0)
对于ng-if也是一样的(在你的plunker中在1.2.15和1.3.0-rc.1之间切换时有相同的奇怪的不同行为).
所以正确的是使用1.3.0-rc.1.
AngualrJS中的Directive制作一个菜单_AngularJS
说下我经常写菜单的方式:
<ul> <li data-ng-> <a href="#/orders">Orders</a> </li> </ul>
菜单项是否高亮显示取决于controller中的highlight方法。
vm.highlight = funciton(path){ return $locaiton.path().substr(0, path.lenght) === path; }
如果以Directive的方式会更简洁。
<ul menu-highlighter highlight-class-name="active"> <li><a href="#/customers">Customers</a></li> <li><a href="#/orders">Customers</a></li> <li><a href="#/about">Customers</a></li> </ul>
Directive大致是:
(function(){ var injectParams = [''$location'']; var menuHighlighter = function($location){ var link = function(scope, element){ function setActive(){ var path = $location.path(); var className = scope.highlightClassName || ''active''; if(path){ angular.forEac(element.find(''li''), function(li){ //<a href="#/customers">Customers</a> var anchor = li.querySelector(''a''); //#/customers var href=(anchor && anchor.href) ? anchor.href : anchor.getAttribute(''data-href'').replace(''#'',''''); //customers var trimmedHref = href.substr(href.indexOf(''#/'')+1, href.length); var basePath = path.substr(0, trimmedHref.length); if(trimmedHref === basePath){ angular.element(li).addClass(className); } else { angular.element(li).removeClass(className); } }); } } setActive(); scope.$on(''$locationChangeSuccess'', setActive); }; return { restrict: ''A'', scope: { highlightClassName: ''@'' }, link: link } }; menuHighlighter.$inject = injectParams; angular.module(''my.directives'') .directive(''menuHighlighter'', menuHighlighter); }());
以上内容是针对AngualrJS中的Directive制作一个菜单的相关知识,希望对大家有所帮助。
Angular 根据 service 的状态更新 directive_AngularJS
angular js (angular.js) 是一组用来开发web页面的框架、模板以及数据绑定和丰富ui组件。它支持整个开发进程,提供web应用的架构,无需进行手工dom操作。
AngularJS是为了克服HTML在构建应用上的不足而设计的。HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了。这里AngularJS就应运而生,弥补了HTML的天然缺陷,用于构件Web应用等。
TL;DR
这篇文章讲解了三种根据 service 的状态更新 directive 的做法。分别是 $watch 表达式,事件传递,和 controller 的计算属性。
问题
我有一个 readerService ,其中包含一些状态信息(比如连接状态和电量)。现在我需要做一个 directive 去展示这些状态。因为它只需要从 readerService 中获取数据,不需要任何外部传值,所以我直接把 service 注入进去。但如何更新就成了一个问题。
service 的代码如下。
const STATUS = { DETACH: ''DETACH'', ATTACH: ''ATTACH'', READY: ''READY'' } class ReaderService { constructor() { this.STATUS = STATUS // The status will be changed by some callbacks this.status = STATUS.DETACH } } angular.module(''app'').service(''readerService'', readerService)
directive 代码如下:
angular.module(''app'').directive(''readerIndicator'', (readerService) => { const STATUS = readerService.STATUS const STATUS_DISPLAY = { [STATUS.DETACH]: ''Disconnected'', [STATUS.ATTACH]: ''Connecting...'', [STATUS.READY]: ''Connected'', } return { restrict: ''E'', scope: {}, template: ` <div> {{statusDisplay}} </div> `, link(scope) { // Set and change scope.statusDisplay here } } })
我尝试过以下几种办法,下面一一介绍。
方法一:$watch
第一个想到的方法就是在 directive 中用 $watch 去监视 readerService.status 。因为它不是 directive scope 的属性,所以我们需要用一个函数来包裹它。Angular 会在 dirty-checking 时计算和比较新旧值,只有状态真的发生了改变才会触发回调。
// In directive link(scope) { scope.$watch(() => readerService.status, (status) => { scope.statusDisplay = STATUS_DISPLAY[status] }) }
这个做法足够简单高效,只要涉及 readerService.status 改变的代码会触发 dirty-checking ,directive 就会自动更新。service 不需要修改任何代码。
但如果有多个 directive 的属性都受 service status 的影响,那 $watch 代码就看得比较晦涩了。尤其是 $watch 修改的值会影响其他的值的时候。比如:
// In directive link(scope) { scope.$watch(() => readerService.status, (status) => { scope.statusDisplay = STATUS_DISPLAY[status] scope.showBattery = status !== STATUS.DETACH }) scope.$watch(''showBattery'', () => { // some other things depend on showBattery }) }
这种时候声明式的编程风格会更容易看懂,比如 Ember 或 Vue 里面的 computed property 。这个待会讨论。
方法二:$broadcast/$emit + $on
这种思路是 service 每次状态改变都发送一个事件,然后 directive 监听事件来改变状态。因为 directive 渲染的时候也许 status 已经更新了。所以我们需要在 link 中计算一个初始值。
我最开始是用 $broadcast 去做的。代码如下:
// In service setStatus(value) { this.status = value // Need to inject $rootScope this.$rootScope.$broadcast(''reader.statusChanged'', this.status) } // In directive link(scope) { scope.statusDisplay = STATUS_DISPLAY[nfcReaderService.status] scope.$on(''reader.statusChanged'', (event, status) => { scope.statusDisplay = STATUS_DISPLAY[status] }) }
但马上发现 $broadcast 之后 UI 更新总要等 1 秒多(不过 $on 回调倒是很快)。Google 一番后知道原因是 $broadcast 是向下层所有 scope 广播,广播完成后再 dirty-checking 。一个更好的做法是使用 $emit ,它只会向上传递事件,不过不管发送事件还是监听事件都得用 $rootScope 。
修改后的代码如下:
// In service setStatus(value) { this.status = value // Use $emit instead of $broadcast this.$rootScope.$emit(''reader.statusChanged'', this.status) } // In directive link(scope) { scope.statusDisplay = STATUS_DISPLAY[nfcReaderService.status] // Use $rootScope instead of scope $rootScope.$on(''reader.statusChanged'', (event, status) => { scope.statusDisplay = STATUS_DISPLAY[status] }) }
如果因为某些原因不得不用 $broadcast 的话,你可以在 $on 回调最后用 $digest 或 $apply 强制触发 dirty-checking ,这也可以达到快速更新 UI 的目的。
方法三:controller + property
我个人觉得前两个方法能解决问题,但代码维护性都不太好。 $watch 在属性相互关联的情况下非常难看懂, $emit/$on 需要把一些逻辑写两次(初始化 directive 时和回调执行时)。方法一中我提到了有些时候声明式的属性比 $watch 更容易看懂。这个方法就是使用 controller 。directive 可以设置自己的 controller 作为数据来源(或者说 view model),我们可以把那些需要计算的属性作为 controller 的属性。这样 dirty-checking 时它们就会自动计算。
// In directive class ReaderController { constructor($scope, readerService) { this.readerService = readerService } get statusDisplay() { return STATUS_DISPLAY[this.readerService.status] } } return { // ... controller: ReaderController, controllerAs: ''vm'', template: ` <div> {{vm.statusDisplay}} </div> }
这样一来,大部分逻辑都可以挪到 controller 中。如果没有 DOM 操作我们甚至可以不写 link 方法。也没必要加入额外的 $watch 和 $on 。只是因为 dirty-checking 的特性,绑定到 template 的属性往往会多计算几次。所以属性必须非常简单。大部分情况下这不会有什么问题。
以上内容是小编给大家介绍的Angular 根据 service 的状态更新 directive,希望对大家有所帮助!
AngularJs Directive Pass value/object/function to Scope
记录一下
@ 单向传递字符串的值。对于外层 scope 的值,可用 {{}} 形式。
= 与父 scope 中的属性进行双向绑定,通常用于对象,无需加 {{}}
& 传递来自父 scope 的函数
angularjs directive semantic-ui pagination
ui.semantic.pagination.js
(function (angular) {
angular.module(''ui.semantic.pagination'', [])
.controller(''PaginationController'', [''$scope'', ''$attrs'', ''$parse'', function ($scope, $attrs, $parse) {
var self = this,
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
this.init = function (ngModelCtrl_, config) {
ngModelCtrl = ngModelCtrl_;
this.config = config;
ngModelCtrl.$render = function () {
self.render();
};
if ($attrs.itemsPerPage) {
$scope.$parent.$watch($parse($attrs.itemsPerPage), function (value) {
self.itemsPerPage = parseInt(value, 10);
$scope.totalPages = self.calculateTotalPages();
});
} else {
this.itemsPerPage = config.itemsPerPage;
}
};
this.calculateTotalPages = function () {
var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);
return Math.max(totalPages || 0, 1);
};
this.render = function () {
$scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;
};
$scope.selectPage = function (page) {
if ($scope.page !== page && page > 0 && page <= $scope.totalPages) {
ngModelCtrl.$setViewValue(page);
ngModelCtrl.$render();
}
};
$scope.getText = function (key) {
return $scope[key + ''Text''] || self.config[key + ''Text''];
};
$scope.noPrevious = function () {
return $scope.page === 1;
};
$scope.noNext = function () {
return $scope.page === $scope.totalPages;
};
$scope.$watch(''totalItems'', function () {
$scope.totalPages = self.calculateTotalPages();
});
$scope.$watch(''totalPages'', function (value) {
setNumPages($scope.$parent, value); // Readonly variable
if ($scope.page > value) {
$scope.selectPage(value);
} else {
ngModelCtrl.$render();
}
});
}])
.constant(''paginationConfig'', {
itemsPerPage: 10,
boundaryLinks: false,
directionLinks: true,
firstText: ''First'',
previousText: ''Previous'',
nextText: ''Next'',
lastText: ''Last'',
numDisplayEntries: 6, //连续分页主体部分分页条目数
numEdgeEntries: 2, //两侧首尾分页条目数
rotate: true
})
.directive(''pagination'', [''$parse'', ''paginationConfig'', function ($parse, paginationConfig) {
return {
restrict: ''EA'',
scope: {
totalItems: ''='',
firstText: ''@'',
previousText: ''@'',
nextText: ''@'',
lastText: ''@''
},
require: [''pagination'', ''?ngModel''],
controller: ''PaginationController'',
templateUrl: ''/UserControls/pagination.html'',
replace: true,
link: function (scope, element, attrs, ctrls) {
var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
if (!ngModelCtrl) {
return; // do nothing if no ng-model
}
// Setup configuration parameters
var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize,
rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate;
scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;
scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks;
var num_display_entries = angular.isDefined(attrs.numDisplayEntries) ? scope.$parent.$eval(attrs.numDisplayEntries) : paginationConfig.numDisplayEntries,
num_edge_entries = angular.isDefined(attrs.numEdgeEntries) ? scope.$parent.$eval(attrs.numEdgeEntries) : paginationConfig.numEdgeEntries;
paginationCtrl.init(ngModelCtrl, paginationConfig);
if (attrs.maxSize) {
scope.$parent.$watch($parse(attrs.maxSize), function (value) {
maxSize = parseInt(value, 10);
paginationCtrl.render();
});
}
// Create page object used in template
function makePage(number, text, isActive) {
return {
number: number,
text: text,
active: isActive,
disabled: text == ''...'',
};
}
function getPages2(currentPage, totalPages) {
var ret = [];
var num_edge_entries = 2;
var np = totalPages;
var interval = getInterval(currentPage - 1, totalPages);
// Generate starting points
if (interval[0] > 0 && num_edge_entries > 0) {
var end = Math.min(num_edge_entries, interval[0]);
for (var i = 0; i < end; i++) {
var page = makePage(i + 1, i + 1, (i + 1) === currentPage);
ret.push(page);
}
if (num_edge_entries < interval[0]) {
var page = makePage(-1, ''...'', false);
ret.push(page);
}
}
// Generate interval links
for (var i = interval[0]; i < interval[1]; i++) {
var page = makePage(i + 1, i + 1, (i + 1) === currentPage);
ret.push(page);
}
// Generate ending points
if (interval[1] < np && num_edge_entries > 0) {
if (np - num_edge_entries > interval[1]) {
var page = makePage(-1, ''...'', false);
ret.push(page);
}
var begin = Math.max(np - num_edge_entries, interval[1]);
for (var i = begin; i < np; i++) {
var page = makePage(i + 1, i + 1, (i + 1) === currentPage);
ret.push(page);
}
}
return ret;
}
function getPages(currentPage, totalPages) {
var pages = [];
// Default page limits
var startPage = 1, endPage = totalPages;
var isMaxSized = (angular.isDefined(maxSize) && maxSize < totalPages);
// recompute if maxSize
if (isMaxSized) {
if (rotate) {
// Current page is displayed in the middle of the visible ones
startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
endPage = startPage + maxSize - 1;
// Adjust if limit is exceeded
if (endPage > totalPages) {
endPage = totalPages;
startPage = endPage - maxSize + 1;
}
} else {
// Visible pages are paginated with maxSize
startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;
// Adjust last page if limit is exceeded
endPage = Math.min(startPage + maxSize - 1, totalPages);
}
}
// Add page number links
for (var number = startPage; number <= endPage; number++) {
var page = makePage(number, number, number === currentPage);
pages.push(page);
}
// Add links to move between page sets
if (isMaxSized && !rotate) {
if (startPage > 1) {
var previousPageSet = makePage(startPage - 1, ''...'', false);
pages.unshift(previousPageSet);
}
if (endPage < totalPages) {
var nextPageSet = makePage(endPage + 1, ''...'', false);
pages.push(nextPageSet);
}
}
return pages;
}
/**
* Calculate start and end point of pagination links depending on
* currentPage and num_display_entries.
* @return {Array}
*/
function getInterval(currentPage, pageCount) {
//var num_display_entries = 6;
//var num_edge_entries = 2;
var ne_half = Math.ceil(num_display_entries / 2);
var np = pageCount;
var upper_limit = np - num_display_entries;
var start = currentPage > ne_half ? Math.max(Math.min(currentPage - ne_half, upper_limit), 0) : 0;
var end = currentPage > ne_half ? Math.min(currentPage + ne_half, np) : Math.min(num_display_entries, np);
return [start, end];
}
var originalRender = paginationCtrl.render;
paginationCtrl.render = function () {
originalRender();
if (scope.page > 0 && scope.page <= scope.totalPages) {
scope.pages = getPages2(scope.page, scope.totalPages);
}
};
}
};
}]);
})(angular);
pagination.html
<div>
<ang-data-ng-click="selectPage(page - 1)">
<i></i>
</a>
<adata-ng-repeat="page in pages track by $index"
data-ng-data-ng-click="selectPage(page.number)">
{{page.text}}
</a>
<ang-data-ng-click="selectPage(page + 1)">
<i></i>
</a>
</div>
今天关于AngularJS Transclusion Directive with ngRepeat导致混合范围的讲解已经结束,谢谢您的阅读,如果想了解更多关于AngualrJS中的Directive制作一个菜单_AngularJS、Angular 根据 service 的状态更新 directive_AngularJS、AngularJs Directive Pass value/object/function to Scope、angularjs directive semantic-ui pagination的相关知识,请在本站搜索。
本文标签: