我创建了一个简单的指令,显示<table>我正在创建的排序列标题.
ngGrid.directive("sortColumn", function() {
return {
restrict: "E",
replace: true,
transclude: true,
scope: {
sortby: "@",
onsort: "="
},
template: "<span><a href='#' ng-click='sort()' ng-transclude></a></span>",
link: function(scope, element, attrs) {
scope.sort = function () {
// I want to call CONTROLLER.onSort here, but how do I access the controller scope?...
scope.controllerOnSort(scope.sortby);
};
}
};
});
Run Code Online (Sandbox Code Playgroud)
以下是一些正在创建的表头的示例:
<table id="mainGrid" ng-controller="GridCtrl>
<thead>
<tr>
<th><sort-column sortby="Name">Name</sort-column></th>
<th><sort-column sortby="DateCreated">Date Created</sort-column></th>
<th>Hi</th>
</tr>
</thead>
Run Code Online (Sandbox Code Playgroud)
因此,当单击排序列时,我想在我的网格控制器上触发onControllerSort函数..但是我被卡住了!到目前为止,我能够做到这一点的唯一方法是为每个<sort-column>添加"onSort"的属性并引用指令中的那些:
<sort-column onSort="controllerOnSort" sortby="Name">Name</sort-column>
Run Code Online (Sandbox Code Playgroud)
但这并不是很好,因为我总是想调用controllerOnSort,所以为每个指令管道都有点难看.如何在指令中执行此操作而不需要在HTML中使用不必要的标记?如果有帮助,指令和控制器都在同一模块中定义.
我正处于从版本1.2.*转换到1.3.*的过程中,我遇到了一个非常奇怪且严重的错误.
在我的应用程序中,我有一个非常简单的directive包含templatewith ng-class(具有范围属性的条件)由于某种原因它不适用于1.3.*版本,并且它与1.2.*版本一起正常工作.
看看这个 Plunker来说明问题.
此Plunker代码使用角度1.2.*版本,您可以看到它的工作正常.
尝试更改角度版本(index.html)
<script src="https://code.angularjs.org/1.3.9/angular.js"></script>
<script src="https://code.angularjs.org/1.3.9/angular-animate.js"></script>
<!--<script src="https://code.angularjs.org/1.2.28/angular.js"></script>
<script src="https://code.angularjs.org/1.2.28/angular-animate.js"></script>-->
Run Code Online (Sandbox Code Playgroud)
刷新页面,然后您可以看到错误:
Angular不会根据'active'属性更改来刷新ng-class.
我试图了解导致此错误的原因,经过大量尝试后我发现该'ngAnimate'模块导致了这个问题.尝试删除'ngAnimate'依赖项(script.js):
//var app = angular.module('app', ['ngAnimate']);
var app = angular.module('app', []);
Run Code Online (Sandbox Code Playgroud)
然后你可以看到一切都很好,因此'ngAnimate'版本1.3.*会导致这个问题.
所以这是AngularJS的错误,我是对的吗?
如果没有,我做错了什么?
angularjs angularjs-directive ng-animate ng-class isolate-scope
我正在尝试从仪表板组件访问我的家庭控制器范围,但它未定义.
我也尝试了第二种方法,但后来我的函数变量未定义.
我正在使用带有Typescript的Angular 1.5
第一种方法:
家庭控制器HTML:
<div class="home-container">
<dashboard-component on-tile-type-changed="HomeCtrl.onTileTypeChanged">
</dashboard-component>
</div>
Run Code Online (Sandbox Code Playgroud)
家庭控制器js:
namespace app.dashboard {
'use strict';
class HomeController {
static $inject:Array<string> = ['$window'];
constructor(private $window:ng.IWindowService) {
}
private onTileTypeChanged(tile:ITile) {
console.log(tile); // DEFINED AND WORKING
console.log(this); // NOT DEFINED
}
}
angular
.module('app.dashboard')
.controller('HomeController', HomeController);
}
Run Code Online (Sandbox Code Playgroud)
仪表板控制器js:
angular.module('app.dashboard')
.component('dashboardComponent', {
templateUrl: 'app/dashboard/directives/dashboard-container.html',
controller: DashboardComponent,
controllerAs: 'DashboardCtrl',
bindings: {
onTileTypeChanged: "&"
}
});
this.onTileTypeChanged()(tile);
Run Code Online (Sandbox Code Playgroud)
第二种方法:
家庭控制器HTML:
<div class="home-container">
<dashboard-component on-tile-type-changed="HomeCtrl.onTileTypeChanged()">
</dashboard-component>
</div>
Run Code Online (Sandbox Code Playgroud)
仪表板控制器js:
this.onTileTypeChanged(tile);
Run Code Online (Sandbox Code Playgroud)
在这里,我正好相反:
private …Run Code Online (Sandbox Code Playgroud) //main controller
angular.module('myApp')
.controller('mainCtrl', function ($scope){
$scope.loadResults = function (){
console.log($scope.searchFilter);
};
});
// directive
angular.module('myApp')
.directive('customSearch', function () {
return {
scope: {
searchModel: '=ngModel',
searchChange: '&ngChange',
},
require: 'ngModel',
template: '<input type="text" ng-model="searchModel" ng-change="searchChange()"/>',
restrict: 'E'
};
});
// html
<custom-search ng-model="searchFilter" ng-change="loadResults()"></custom-search>
Run Code Online (Sandbox Code Playgroud)
这是一个简化的指令来说明.当我输入到输入,我预计console.log在loadResults注销正是我已经输入.它实际上记录了一个字符,因为loadResults它正好在searchFilter主控制器中的var从指令接收新值之前运行.但是,在指令内部记录,一切都按预期工作.为什么会这样?
我的解决方案
得到什么在我的简单的例子与ngChange发生的事件的了解之后,我意识到我的实际问题的事实,我其实传入ngModel是一个对象,其属性我改变,也说我有点复杂使用此指令的表单验证作为输入之一.我发现在指令中使用$ timeout和$ eval解决了我所有的问题:
//main controller
angular.module('myApp')
.controller('mainCtrl', function ($scope){
$scope.loadResults = function (){
console.log($scope.searchFilter);
};
});
// directive
angular.module('myApp')
.directive('customSearch', function ($timeout) {
return { …Run Code Online (Sandbox Code Playgroud) 我发现这个问题让我几乎到了我需要的地方. 为什么ng-click不能在我的指令中工作?如何添加切换类?
这使得我的指令模板中的ng-click触发了我的控制器中的一个功能. http://plnkr.co/edit/GorcZZppa8qcIKbQAg2v?p=preview
问题是返回到我的控制器(项目)的参数是未定义的.我需要这个实际传递来自我的指令中的变量的数据,以便在我将在控制器中运行的函数中使用.
指令模板文件
<div class="tsProductAttribute"
ng-class="{'tsProductAttribute--selected': selected}"
ng-click="toggleState(item)">
<span class="tsProductAttribute-image">
<img ng-src="{{variantImage}}">
</span>
<span class="tsProductAttribute-desc">{{item.productName}}</span>
<select ng-model="variantImage">
<option ng-repeat="variant in item.variants" value="{{variant.image}}">{{variant.name}} - {{variant.listprice.amount}}</option>
</select>
<span class="tsProductAttribute-price">{{item.variants[0].listprice.amount}} {{item.variants[0].listprice.entity}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)
指示
angular.module('msfApp')
.directive('listitem', function () {
return {
templateUrl: 'assets/templates/directives/listitem.html',
restrict: 'E',
scope: {
'item': '=',
'itemClick': '&'
},
link: function(scope, iElement, iAttrs) {
scope.selected = false;
scope.toggleState = function(item) {
scope.selected = !scope.selected;
scope.itemClick(item);
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
指令实施
<listitem item="item" item-click="toggleInBasket(item)"></listitem>
Run Code Online (Sandbox Code Playgroud)
控制器中的功能
$scope.toggleInBasket = …Run Code Online (Sandbox Code Playgroud) 根据AngularJS开发人员指南 - 指令"隔离指令的范围",范围绑定可以在3种类型中完成
=,@和&
和
根据本页的"指令定义对象"部分,范围绑定可以在4种类型中完成
=,@,&和<
即使在大多数在线文章中,也只提供了3种类型的范围绑定.
哪个是对的?
angularjs angularjs-scope angular-directive isolate-scope angular-components
在AngularJS中,一个指令如何使用基于事件的通信($emit,$broadcast和$on)与另一个具有隔离范围的指令进行通信?我已经创建了两个指令,当从第二个指令中删除隔离范围时,第一个指令能够使用emit成功地与第二个指令进行通信.但是,当隔离范围添加回第二个时,通信会中断.
var app = angular.module('myApp', []);
app.directive("firstDir", function() {
return {
restrict: 'E',
controller: function($scope) {
$scope.set = function() {
$scope.$emit('MY_NEW_SEARCH', $scope.searchQuery);
}
},
template: '<input type="text" ng-model="searchQuery"><button ng-click="set()">Change Value</button>'
};
});
app.directive("secondDir", function() {
return {
restrict : 'E',
scope: {},
controller : function($scope) {
var _that = $scope;
$scope.$on('MY_NEW_SEARCH', function(e, data) {
_that.data = data;
});
$scope.data = 'init value';
}
};
});
Run Code Online (Sandbox Code Playgroud)
我创建了一个Plunker来说明问题.您会注意到,如果您在第二个指令的指令定义对象中注释掉"scope"属性,则通信可以正常工作:您可以在第一个指令的输入框中键入一个字符串,按下第一个指令的按钮指令,并将字符串传递给第二个指令,该指令将其显示在视图上.(就目前而言,由于隔离范围问题,Plunker已损坏,请参阅app.js文件的第19行.)
http://plnkr.co/edit/AXUVX9zdJx1tApDhgH32
这是我的首要目标:我为第二个指令使用隔离范围的原因是将范围内部与范围外部区分开来.(我的项目中使用的实际"第二指令"比这个玩具示例复杂得多.这就是必要的.)我知道AngularJS提供了将外部范围映射到指令内部范围的机制.我很好奇这些机制中的任何一个对于映射基于事件的通信事件是否有用.
如果答案结果是隔离范围对于基于事件的通信是不可克服的,那么在我已经说明的情况下完成指令通信指令的最佳方法是什么,同时仍然实现我的目标?谢谢!
我真的不明白为什么这段代码按照它的方式工作.
我调用我的服务并返回预期的数据.我希望单独存储图片,因为我需要修改数组并以不同方式解析新范围.我不明白的是,因为我现在已经创建了2个范围,产品和产品图片 - 为什么这些仍然相关?
如果我将Lodash用于_.sort()productPictures,那么scope.Product中的Images对象也将被更改,但我不希望这种情况发生,我不知道如何隔离$ scope.productPictures.我尝试将范围作为简单的js变量处理,例如var product; 和var productPictures,但是当我根据服务的响应设置数据时,它们仍然是链接的.
$api.productpage.query({
id: parseInt($stateParams.productId)
}, function (data) {
$scope.product = data[0];
$scope.productPictures = data[0]['Images'];
});
Run Code Online (Sandbox Code Playgroud)
我忽略了一些超级微不足道的东西吗?我是否应该在单独的服务请求中管理产品图像?
所有,
当涉及到指令时,我对angularjs的理解是当你有一个像这样的隔离范围设置时:
scope: {
dataSource: '='
}
Run Code Online (Sandbox Code Playgroud)
在链接功能内: function(scope, ele, attr)
如果像这样使用,scope将有一个dataSource绑定到name我的控制器上的属性:
<my-element data-source='name'></my-element>
然而事实并非如此,这是一个例子:
http://jsfiddle.net/HB7LU/21879/
谢谢
史蒂夫