AngularJs | ng-click 不触发
AngularJs | ng-click not firing
我看不出 ng-click
不起作用的明显原因,但是当单击它绑定到的元素时它不会触发。
将呈现两个元素。每个 div 的右上角都有一个 X 图标,它应该触发 deletePreview
。这将导致当前删除 linkPreviews
的第一项。例如,当通过 $timeout
调用此方法时,它会按预期工作。但是,尝试单击该图标无效。
我很高兴有任何想法。
(function (angular) {
'use strict';
angular
.module('commons.ui')
.directive('linkPreview', linkPreview)
.controller('LinkPreviewController', LinkPreviewController);
function linkPreview() {
return {
restrict: 'E',
replace: true,
templateUrl: 'link-preview/link-preview.html',
scope: {},
require: 'ngModel',
bindToController: {
focusVar: '=?',
placement: '@'
},
controller: 'LinkPreviewController',
controllerAs: '$ctrl'
};
}
function LinkPreviewController($log, $timeout) {
var vm = this;
vm.deletePreview = deletePreview;
vm.linkPreviews = [
{
image: {
fileId: 'f616157b-223d-46ff-ba87-c16d10e83ed6',
senderId: '1ae6f889-f27e-4466-a0a9-021923704097'
},
title: 'Title',
description: 'This is an integrated platform for your official company news, social collaboration and team messaging.',
url: 'http://www.sample.com/en/tour',
tld: 'sample.com'
},
{
image: '',
title: 'Hacker News',
description: 'News for the technically interested',
url: 'https://news.ycombinator.com/',
tld: 'news.ycombinator.com'
}
];
function deletePreview() {
$log.info('should be deleted');
vm.linkPreviews.splice(0, 1);
}
}
})(angular);
<div ng-repeat="linkPreview in $ctrl.linkPreviews">
<div class="link-preview">
<div class="link-preview-delete pull-right">
<div class="link-preview-delete pull-right">
<span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
<i class="zmdi zmdi-close img-close"></i>
</span>
</div>
</div>
..
</div>
</div>
你在控制器中的函数声明错误。
要使用来自控制器的功能,您需要将其设置为
this.deletePreview
或
$scope.deletePreview
(在后一种情况下,您不必在 ng-click
视图中编写 $ctrl
。记得注入 $scope
!)。
您需要将 empty dependency
添加到您的模块中,例如:
angular.module('commons.ui', [])
并且,必须在 HTML 中使用 controller as
语法(如果未使用),例如:
ng-controller="LinkPreviewController as $ctrl"
工作演示:
angular
.module('commons.ui', [])
.directive('coyoLinkPreview', linkPreview)
.controller('LinkPreviewController', LinkPreviewController);
function linkPreview() {
return {
restrict: 'E',
replace: true,
templateUrl: 'app/commons/ui/components/link-preview/link-preview.html',
scope: {},
require: 'ngModel',
bindToController: {
focusVar: '=?',
placement: '@'
},
controller: 'LinkPreviewController',
controllerAs: '$ctrl'
};
}
function LinkPreviewController($log, $timeout) {
var vm = this;
vm.deletePreview = deletePreview;
vm.linkPreviews = [{
image: {
fileId: 'f616157b-223d-46ff-ba87-c16d10e83ed6',
senderId: '1ae6f889-f27e-4466-a0a9-021923704097'
},
title: 'Go COYO',
description: 'COYO is an integrated platform for your official company news, social collaboration and team messaging.',
url: 'http://www.coyoapp.com/en/tour',
tld: 'coyoapp.com'
}, {
image: '',
title: 'Hacker News',
description: 'News for the technically interested',
url: 'https://news.ycombinator.com/',
tld: 'news.ycombinator.com'
}];
function deletePreview() {
console.log('clicked');
$log.info('should be deleted');
vm.linkPreviews.splice(0, 1);
}
}
<script src="https://code.angularjs.org/1.5.2/angular.js"></script>
<div ng-app="commons.ui" ng-controller="LinkPreviewController as $ctrl">
<div ng-repeat="linkPreview in $ctrl.linkPreviews">
<div class="link-preview">
<div class="link-preview-delete pull-right">
<div class="link-preview-delete pull-right">
<span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
<i class="zmdi zmdi-close img-close">spanToClick</i>
</span>
</div>
</div>
</div>
</div>
</div>
更新:
在您的指令中,您使用的是 scope:{}
,它会创建 isolated scope
,因此您的代码不起作用。
现在进一步 ng-repeat
创建 new child scope
,所以你的 div gets repeated
但 ng-repeat
的内部逻辑(如删除点击)在 new child scope
下,所以它不会'没用。
如果你这样做 $parent.$ctrl
那么它将指向父级并且会起作用。
看到这个plunker
总的来说,最简单的解决方法是从指令中删除独立作用域。 scope: {}
我猜这是 AngularJS 中的错误?或者我确实用错了。
在我的示例中,指令的顶部 html 元素是 <div ng-repeat="linkPreview in $ctrl.linkPreviews">
,这意味着多个 div 将被添加到同一层级。
将它包装在另一个 div 中时,正如@anoop 的示例所示,它会突然起作用。我还不明白的是,为什么 vm.linkPreviews
的数组总是附加到控制器上,而函数 vm.deletePreviews
只有在包裹在一个顶部 div 中时才会起作用。
工作HTML代码:
<div>
<div ng-repeat="linkPreview in $ctrl.linkPreviews">
<div class="link-preview">
<div class="link-preview-delete pull-right">
<span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
<i class="zmdi zmdi-close img-close"></i>
</span>
</div>
<div class="link-preview-image-wrapper">
<div class="link-preview-image">
<coyo-image-reference ng-if="linkPreview.image"
file-id="::linkPreview.image.fileId"
sender-id="::linkPreview.image.senderId"
size-definitions="{'default': 'S', 'screen-lg': 'S'}"></coyo-image-reference>
<div class="link-preview-icon" ng-if="!linkPreview.image">
<i class="zmdi zmdi-globe"></i>
</div>
</div>
</div>
<div class="link-preview-text-wrapper">
<div class="link-preview-line">
<span class="link-preview-title" ng-bind="::linkPreview.title"></span>
</div>
<div class="link-preview-line">
<span class="link-preview-description" ng-bind="::linkPreview.description"></span>
</div>
<div class="link-preview-line">
<span class="link-preview-url">
<a href="{{ ::linkPreview.url }}" target="_blank">{{ ::linkPreview.tld }}</a>
</span>
</div>
</div>
</div>
</div>
</div>
我看不出 ng-click
不起作用的明显原因,但是当单击它绑定到的元素时它不会触发。
将呈现两个元素。每个 div 的右上角都有一个 X 图标,它应该触发 deletePreview
。这将导致当前删除 linkPreviews
的第一项。例如,当通过 $timeout
调用此方法时,它会按预期工作。但是,尝试单击该图标无效。
我很高兴有任何想法。
(function (angular) {
'use strict';
angular
.module('commons.ui')
.directive('linkPreview', linkPreview)
.controller('LinkPreviewController', LinkPreviewController);
function linkPreview() {
return {
restrict: 'E',
replace: true,
templateUrl: 'link-preview/link-preview.html',
scope: {},
require: 'ngModel',
bindToController: {
focusVar: '=?',
placement: '@'
},
controller: 'LinkPreviewController',
controllerAs: '$ctrl'
};
}
function LinkPreviewController($log, $timeout) {
var vm = this;
vm.deletePreview = deletePreview;
vm.linkPreviews = [
{
image: {
fileId: 'f616157b-223d-46ff-ba87-c16d10e83ed6',
senderId: '1ae6f889-f27e-4466-a0a9-021923704097'
},
title: 'Title',
description: 'This is an integrated platform for your official company news, social collaboration and team messaging.',
url: 'http://www.sample.com/en/tour',
tld: 'sample.com'
},
{
image: '',
title: 'Hacker News',
description: 'News for the technically interested',
url: 'https://news.ycombinator.com/',
tld: 'news.ycombinator.com'
}
];
function deletePreview() {
$log.info('should be deleted');
vm.linkPreviews.splice(0, 1);
}
}
})(angular);
<div ng-repeat="linkPreview in $ctrl.linkPreviews">
<div class="link-preview">
<div class="link-preview-delete pull-right">
<div class="link-preview-delete pull-right">
<span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
<i class="zmdi zmdi-close img-close"></i>
</span>
</div>
</div>
..
</div>
</div>
你在控制器中的函数声明错误。
要使用来自控制器的功能,您需要将其设置为
this.deletePreview
或
$scope.deletePreview
(在后一种情况下,您不必在 ng-click
视图中编写 $ctrl
。记得注入 $scope
!)。
您需要将 empty dependency
添加到您的模块中,例如:
angular.module('commons.ui', [])
并且,必须在 HTML 中使用 controller as
语法(如果未使用),例如:
ng-controller="LinkPreviewController as $ctrl"
工作演示:
angular
.module('commons.ui', [])
.directive('coyoLinkPreview', linkPreview)
.controller('LinkPreviewController', LinkPreviewController);
function linkPreview() {
return {
restrict: 'E',
replace: true,
templateUrl: 'app/commons/ui/components/link-preview/link-preview.html',
scope: {},
require: 'ngModel',
bindToController: {
focusVar: '=?',
placement: '@'
},
controller: 'LinkPreviewController',
controllerAs: '$ctrl'
};
}
function LinkPreviewController($log, $timeout) {
var vm = this;
vm.deletePreview = deletePreview;
vm.linkPreviews = [{
image: {
fileId: 'f616157b-223d-46ff-ba87-c16d10e83ed6',
senderId: '1ae6f889-f27e-4466-a0a9-021923704097'
},
title: 'Go COYO',
description: 'COYO is an integrated platform for your official company news, social collaboration and team messaging.',
url: 'http://www.coyoapp.com/en/tour',
tld: 'coyoapp.com'
}, {
image: '',
title: 'Hacker News',
description: 'News for the technically interested',
url: 'https://news.ycombinator.com/',
tld: 'news.ycombinator.com'
}];
function deletePreview() {
console.log('clicked');
$log.info('should be deleted');
vm.linkPreviews.splice(0, 1);
}
}
<script src="https://code.angularjs.org/1.5.2/angular.js"></script>
<div ng-app="commons.ui" ng-controller="LinkPreviewController as $ctrl">
<div ng-repeat="linkPreview in $ctrl.linkPreviews">
<div class="link-preview">
<div class="link-preview-delete pull-right">
<div class="link-preview-delete pull-right">
<span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
<i class="zmdi zmdi-close img-close">spanToClick</i>
</span>
</div>
</div>
</div>
</div>
</div>
更新:
在您的指令中,您使用的是 scope:{}
,它会创建 isolated scope
,因此您的代码不起作用。
现在进一步 ng-repeat
创建 new child scope
,所以你的 div gets repeated
但 ng-repeat
的内部逻辑(如删除点击)在 new child scope
下,所以它不会'没用。
如果你这样做 $parent.$ctrl
那么它将指向父级并且会起作用。
看到这个plunker
总的来说,最简单的解决方法是从指令中删除独立作用域。 scope: {}
我猜这是 AngularJS 中的错误?或者我确实用错了。
在我的示例中,指令的顶部 html 元素是 <div ng-repeat="linkPreview in $ctrl.linkPreviews">
,这意味着多个 div 将被添加到同一层级。
将它包装在另一个 div 中时,正如@anoop 的示例所示,它会突然起作用。我还不明白的是,为什么 vm.linkPreviews
的数组总是附加到控制器上,而函数 vm.deletePreviews
只有在包裹在一个顶部 div 中时才会起作用。
工作HTML代码:
<div>
<div ng-repeat="linkPreview in $ctrl.linkPreviews">
<div class="link-preview">
<div class="link-preview-delete pull-right">
<span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
<i class="zmdi zmdi-close img-close"></i>
</span>
</div>
<div class="link-preview-image-wrapper">
<div class="link-preview-image">
<coyo-image-reference ng-if="linkPreview.image"
file-id="::linkPreview.image.fileId"
sender-id="::linkPreview.image.senderId"
size-definitions="{'default': 'S', 'screen-lg': 'S'}"></coyo-image-reference>
<div class="link-preview-icon" ng-if="!linkPreview.image">
<i class="zmdi zmdi-globe"></i>
</div>
</div>
</div>
<div class="link-preview-text-wrapper">
<div class="link-preview-line">
<span class="link-preview-title" ng-bind="::linkPreview.title"></span>
</div>
<div class="link-preview-line">
<span class="link-preview-description" ng-bind="::linkPreview.description"></span>
</div>
<div class="link-preview-line">
<span class="link-preview-url">
<a href="{{ ::linkPreview.url }}" target="_blank">{{ ::linkPreview.tld }}</a>
</span>
</div>
</div>
</div>
</div>
</div>