如何在没有隔离范围的情况下将变量从指令发送到父控制器
How to Send Variable to Parent Controller from Directive without Isolate Scope
如何在控制器中查看来自指令的变量AngularJS?
我有一个带有控制器和指令的组件
在我的指令中,我正在侦听滚动,如果元素在视图中则返回 true,否则返回 false。
我希望能够在控制器中访问我的 boolChangeClass
变量,以便只有当它为真时我才能调用我的函数。
我的问题是如何在控制器中访问 boolChangeClass
?
'use strict';
angular.module('myModule')
.component('myComponent', {
template: `
<div class="component" inview ng-class="{min: boolChangeClass}">
</div>
`,
controller: function ($scope) {
let $ctrl = this;
let func = () => {console.log('my function')}
$scope.$watch('boolChangeClass', func);
}
})
.directive('inview', ($window) => {
return function(scope, element, attrs) {
angular.element($window).bind("scroll", function() {
let rect = element[0].getBoundingClientRect();
scope.boolChangeClass = rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
rect.top < (window.innerHeight || document.documentElement.clientHeight)
scope.$apply();
});
};
})
tl;博士;
从使用 scope:false
:
的指令向父控制器发送变量
<div on-scroll="$ctrl.fn($event)"></div>
scope.$apply( () => {
scope.$eval(attrs.onScroll, {$event: event});
});
回答
不是用 ng-class
设置 class,而是让指令设置 class:
<div class="component" inview-class="min" ̶n̶g̶-̶c̶l̶a̶s̶s̶=̶"̶{̶m̶i̶n̶:̶ ̶b̶o̶o̶l̶C̶h̶a̶n̶g̶e̶C̶l̶a̶s̶s̶}̶" >
</div>
app.directive('inviewClass', ($window) => {
return function(scope, elem, attrs) {
angular.element($window).on("scroll", function(event) {
let rect = elem[0].getBoundingClientRect();
let boolChangeClass = rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
rect.top < (window.innerHeight || document.documentElement.clientHeight);
let className = attrs.inviewClass;
boolChangeClass ? elem.addClass(className) : elem.removeClass(className);
});
};
})
这避免了涉及 AngularJS 摘要循环、修改 $scope 和添加观察者。
更新
And what should I do in my controller? Check if class exists and then call he method?
使用属性指定在滚动事件上调用的函数:
<div class="component" inview-class="min" on-scroll="$ctrl.fn($event)" >
</div>
app.directive('inviewClass', ($window) => {
return function(scope, elem, attrs) {
angular.element($window).on("scroll", function(event) {
let rect = elem[0].getBoundingClientRect();
let boolChangeClass = rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
rect.top < (window.innerHeight || document.documentElement.clientHeight);
let className = attrs.inviewClass;
boolChangeClass ? elem.addClass(className) : elem.removeClass(className);
//
event.inview = {};
event.inview[className] = boolChangeClass;
scope.$apply( () => {
scope.$eval(attrs.onScroll, {$event: event});
});
});
};
})
在每个滚动事件中,该指令会将 on-scroll
属性评估为一个 AngularJS 表达式,使用 $event 作为本地表达式。
更新 #2
But what if I want to call method in controller on scroll but only once when my variable is true? I tried to use one-time binding but it doesn't really work.
让控制器过滤事件会更明智:
<div class="component" inview-class="min" on-scroll="$ctrl.fn($event)" >
</div>
var minOnce;
this.fn = (event) => {
if (minOnce || !event.inview.min) return;
//ELSE
minOnce = true;
//
// ...
};
这样指令更通用,测试也更容易。
如何在控制器中查看来自指令的变量AngularJS?
我有一个带有控制器和指令的组件
在我的指令中,我正在侦听滚动,如果元素在视图中则返回 true,否则返回 false。
我希望能够在控制器中访问我的 boolChangeClass
变量,以便只有当它为真时我才能调用我的函数。
我的问题是如何在控制器中访问 boolChangeClass
?
'use strict';
angular.module('myModule')
.component('myComponent', {
template: `
<div class="component" inview ng-class="{min: boolChangeClass}">
</div>
`,
controller: function ($scope) {
let $ctrl = this;
let func = () => {console.log('my function')}
$scope.$watch('boolChangeClass', func);
}
})
.directive('inview', ($window) => {
return function(scope, element, attrs) {
angular.element($window).bind("scroll", function() {
let rect = element[0].getBoundingClientRect();
scope.boolChangeClass = rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
rect.top < (window.innerHeight || document.documentElement.clientHeight)
scope.$apply();
});
};
})
tl;博士;
从使用 scope:false
:
<div on-scroll="$ctrl.fn($event)"></div>
scope.$apply( () => {
scope.$eval(attrs.onScroll, {$event: event});
});
回答
不是用 ng-class
设置 class,而是让指令设置 class:
<div class="component" inview-class="min" ̶n̶g̶-̶c̶l̶a̶s̶s̶=̶"̶{̶m̶i̶n̶:̶ ̶b̶o̶o̶l̶C̶h̶a̶n̶g̶e̶C̶l̶a̶s̶s̶}̶" >
</div>
app.directive('inviewClass', ($window) => {
return function(scope, elem, attrs) {
angular.element($window).on("scroll", function(event) {
let rect = elem[0].getBoundingClientRect();
let boolChangeClass = rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
rect.top < (window.innerHeight || document.documentElement.clientHeight);
let className = attrs.inviewClass;
boolChangeClass ? elem.addClass(className) : elem.removeClass(className);
});
};
})
这避免了涉及 AngularJS 摘要循环、修改 $scope 和添加观察者。
更新
And what should I do in my controller? Check if class exists and then call he method?
使用属性指定在滚动事件上调用的函数:
<div class="component" inview-class="min" on-scroll="$ctrl.fn($event)" >
</div>
app.directive('inviewClass', ($window) => {
return function(scope, elem, attrs) {
angular.element($window).on("scroll", function(event) {
let rect = elem[0].getBoundingClientRect();
let boolChangeClass = rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
rect.top < (window.innerHeight || document.documentElement.clientHeight);
let className = attrs.inviewClass;
boolChangeClass ? elem.addClass(className) : elem.removeClass(className);
//
event.inview = {};
event.inview[className] = boolChangeClass;
scope.$apply( () => {
scope.$eval(attrs.onScroll, {$event: event});
});
});
};
})
在每个滚动事件中,该指令会将 on-scroll
属性评估为一个 AngularJS 表达式,使用 $event 作为本地表达式。
更新 #2
But what if I want to call method in controller on scroll but only once when my variable is true? I tried to use one-time binding but it doesn't really work.
让控制器过滤事件会更明智:
<div class="component" inview-class="min" on-scroll="$ctrl.fn($event)" >
</div>
var minOnce;
this.fn = (event) => {
if (minOnce || !event.inview.min) return;
//ELSE
minOnce = true;
//
// ...
};
这样指令更通用,测试也更容易。