#angularjs #angularjs-directive #angularjs-ng-click
#angularjs #angularjs-директива #angularjs-ng-click
Вопрос:
Я могу заставить ng-click работать, когда область действия наследуется в директиве, но не при изоляции. UPDATE: The point is that I want the click function to be defined as part of the directive... moving the function definition into a different scope is not what I want.
Вот рабочий пример с унаследованной областью действия: https://codepen.io/anon/pen/PGBQvj
Вот неработающий пример с изолированной областью действия; https://codepen.io/anon/pen/jrpkjp
(Щелкните числа, они увеличиваются в первом примере, но не во втором)
Некоторый код…
HTML
<div ng-app="myApp" ng-controller="baseController">
<my-directive ng-click="hello()" current="current"></my-directive>
</div>
Директива с унаследованной областью действия:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
scope.hello = function() {
scope.current
};
},
replace: true,
scope: true,
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
Та же директива, но с изолированной областью действия:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
scope.hello = function() {
scope.current
};
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
Ответ №1:
Проблема в том, что вы пытаетесь вызвать функцию, которая не определена. Если вы хотите, чтобы логика была определена внутри изолированной директивы, нет необходимости передавать ссылку на функцию.
<my-directive current="current"></my-directive>
Вы не можете пройти ng-click="hello()"
здесь. Это область действия контроллера, поэтому hello()
она не определена.
Вместо этого переместите ng-click
событие в шаблон директивы
template: '<div ng-click="hello()">
Один дополнительный момент:
Вы используете link()
функцию директивы. Это зарезервировано для манипулирования DOM. Вместо этого определите hello()
внутри controller
функции.
controller: function ($scope) {
$scope.hello = function() {
$scope.current
}
},
Я думаю, что здесь есть более серьезная архитектурная проблема. Цель изолированной директивы или компонента — инкапсулировать внутреннюю логику для себя. Он не должен манипулировать внешним состоянием. В этом примере вы увеличиваете число. Что, если в другой части вашего приложения вы хотите уменьшить число? Копирование директивы с логикой уменьшения приведет к большому дублированию кода.
Вместо этого вы должны определить функциональность увеличения или уменьшения в контроллере и передать ее в директиву.
<my-directive change-number="increment()" current="current"></my-directive>
Затем используйте amp;
синтаксис, чтобы привязать ссылку на функцию к директиве:
scope: {
current:'=',
changeNumber: 'amp;'
},
и звоните changeNumber
из шаблона. Это очень облегчает повторное использование кода.
Ответ №2:
Добавьте функцию приветствия к контроллеру. Пусть он обновит значение current и передаст его в изолированную область действия директивы
.controller('baseController', function($scope) {
$scope.current = 1;
$scope.hello = function() {
$scope.current ;
};
})
Ответ №3:
вам нужно передать объект из контроллера в директиву
измените свой js на
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = {};
$scope.current.val=1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) { scope.internalcurrent= scope.current || {};
//scope.internalcurrent.val=1;
scope.internalcurrent.hello = function() {
scope.internalcurrent.val
};
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ internalcurrent.val }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
и ваш html для
<div ng-app="myApp" ng-controller="baseController">
<my-directive ng-click="hello()" current="current"></my-directive>
</div>
Ответ №4:
Если вы хотите, чтобы функция click была определена в директиве, вам нужно прикрепить обработчик к шаблону следующим образом:
template: '<div ng-click="hello()"><child><strong>{{current}}</strong></child></div>'
Когда вы присоединяете обработчик к объявлению директивы, как в вашем сломанном примере, вы в основном сообщаете ng-click, что хотите вызвать функцию в текущей области видимости (области контроллера). Может показаться, что это не так, потому что в вашем рабочем примере ваша функция была определена из myDirective, но на самом деле она была привязана к области действия, которая в данном случае (рабочий пример) была областью действия контроллера.
Ответ №5:
С изолированной директивой вы можете использовать ng-click="$parent.hello()"
вместо ng-click="hello()"
. Приятно опубликовать перья в вашем вопросе.
Объяснение: когда вы используете ng-click
для элемента, значение it ( hello()
) будет оцениваться относительно его внешней области, то есть области контроллера в вашем примере. Когда вы создаете директиву, которая использует неизолированную область, область контроллера передается link
функции и hello
определяется в области контроллера.
// Редактировать код:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
$scope.hello = () => $scope.current ;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
Комментарии:
1. Извините, я неправильно понял ваш вопрос. Определите
hello()
область действия вашего контроллера, и он должен work.@geoidesic2. Это тоже не работает. Пожалуйста, попробуйте, прежде чем предлагать 🙂 tx.
3. Если я вас неправильно понял, функция hello() уже определена в области действия контроллера.
4. Когда вы используете директиву с изолированной областью действия, она влияет только на оценку внутри элемента. @geoidesic
5. Ваше решение работает, но на самом деле оно мне не полезно. Я не хочу перемещать свою функцию из контроллера директив.