Использование начальной загрузки с компонентами AngularJS не работает, если нужно инкапсулировать внутренние элементы Bootstrap в компонентах, поскольку дополнительная разметка самого компонента, добавленного в DOM, нарушает правила CSS с прямым дочерним оператором >
. Например, при реализации DropDown необходимо создать полный компонент с DropDown и создать каждую опцию раскрывающегося списка внутри этого полного компонента с ng-repeat
, считывающими данные из массива конфигурации. Что-то вроде этого:
<my-bootstrap-drop-down
my-label="Some label"
my-options="[ { label: 'Option1 }, {label: 'Option2'} ]" >
</my-bootstrap-drop-down>
Из Дэна Уолина " Создание настраиваемых директив AngularJS ", чтобы иметь возможность передавать функцию с переменным количеством аргументов компоненту AngularJS, вам понадобится специальный синтаксис, в котором вы передаете ссылку на функцию атрибуту тега элемента следующим образом:
<my-component
my-action="myMethod(p1, p2)"
my-params="{p1:1, p2:25}">
</my-componenet>
А затем в компоненте вы вызываете функцию с помощью этого кода:
<a ng-click="$ctrl.myAction($ctrl.myParams)"></a>
Этот синтаксис работает правильно только при использовании в атрибутах элемента, отображаемых с помощью оператора &
как привязки компонента / директивы. Даже когда my-action="myMethod(p1, p2)
кажется вызовом функции, на самом деле это передача по ссылке. К сожалению, если вы хотите использовать ng-repeat
для генерации некоторого кода внутри компонента, как описано выше, нет никакого способа заставить этот синтаксис работать, поскольку синтаксис myThethod(p1, p2)
работает только в атрибуте.
Итак, как вы можете реализовать компонент, имеющий массив внутренних элементов, сгенерированных с помощью ng-repeat
, и эти элементы, имеющие вызовы функций с переменным числом аргументов, поскольку более поздний синтаксис не работает?
<my-bootstrap-drop-down
my-label="Some label"
my-options="[
{ label: 'Option1', action: myMethod(p1, p2), params: {p1:1, p2:25}},
...
]" >
</my-bootstrap-drop-down>
При попытке выполнить этот код myMethod(p1, p2)
выполняется при создании компонента, поскольку это фактически вызов функции, а не передача по ссылке.
Примечание . В той же статье, упомянутой выше, предлагается другой синтаксис для вызова функций. Синтаксис предполагает, что компонент знает, сколько аргументов передать, что не так. Его можно было бы использовать в любом случае, передавая аргументы в виде массива и вызывая функцию с помощью apply
, но применение не разрешено в выражениях angular.
Я добавил Plunker, чтобы было понятно:
https://plnkr.co/edit/dkofEYhebp0T6lSf22RP?p=preview
1 ответ
Изменить: Хорошо, не знаю, зачем вам это нужно, но у меня это работает: https://plnkr.co/edit/uR9s5vUJxQoviTiUD2vj?p=preview
И то же самое, но с использованием Директивы: https://plnkr.co/edit/Onh2WonmarpUscnFFLGK?p=preview
Конец редактирования
Вы должны передать переменную в my-options (назовем ее dropDownOptions):
<my-bootstrap-drop-down
my-label="Some label"
my-options="dropDownOptions" >
</my-bootstrap-drop-down>
И массив dropDownOptions должен содержать данные, которые вам нужны в директиве, но только данные, а не функцию: [{"label": "Option 1", "params": {"p1": 1, "p2": 25}}, ...]
Теперь внутри вашей директивы у вас есть доступ к данным и вы можете работать над частью действия / функции. Пример:
var testApp = angular.module('testApp', []);
testApp.controller('mainCtrl', ['$scope',
function ($scope) {
$scope.test = "Hi";
$scope.dropDownOptions = [{"name": "yes", "value": 2}, {"name": "no", "value": 25}];
}]);
testApp.directive('myBootstrapDropDown', function () {
return {
restrict: 'E',
scope: {
myLabel: '@',
myOptions: '='
},
controller: function ($scope) {
$scope.myMethod = function (val) {
alert("There was a change, new value: " + val);
};
},
template: '<label>{{myLabel}}</label> <select name="myLabel" ng-model="myValue" ng-options="opt.value as opt.name for opt in myOptions" ng-change="myMethod(myValue)"><option value=""> </option></select>'
};
});
<!DOCTYPE html>
<html lang="en" ng-app="testApp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Sample</title>
<style>
.starter-template {
padding: 10px 15px;
text-align: center;
}
a {
font-size: 11px;
cursor: pointer;
}
</style>
</head>
<body>
<div ng-controller="mainCtrl">
<div class="container">
<div class="starter-template">
<h1>Example</h1>
<p class="lead">{{test}}</p>
<my-bootstrap-drop-down
my-label="Some label"
my-options="dropDownOptions" >
</my-bootstrap-drop-down>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="app.js"></script>
</body>
</html>
Таким образом, вам не нужно связывать функцию с вашей директивой, если только директива не должна запускать что-то обратно в контроллере, и в этом случае вы должны поместить функцию в отдельный атрибут (который в этом случае будет связан с & как вы упомянули).
Например:
var testApp = angular.module('testApp', []);
testApp.controller('mainCtrl', ['$scope',
function ($scope) {
$scope.test = "Hi";
$scope.dropDownOptions = [{"name": "yes", "value": 2}, {"name": "no", "value": 25}];
$scope.runThis = function (val) {
//Do Something here
alert("There was a change, new value: " + val);
};
}]);
testApp.directive('myBootstrapDropDown', function () {
return {
restrict: 'E',
scope: {
myLabel: '@',
myOptions: '=',
myFunction: "&"
},
controller: function ($scope) {
$scope.myMethod = function (val) {
$scope.myFunction()(val);
};
},
template: '<label>{{myLabel}}</label> <select name="myLabel" ng-model="myValue" ng-options="opt.value as opt.name for opt in myOptions" ng-change="myMethod(myValue)"><option value=""> </option></select>'
};
});
<!DOCTYPE html>
<html lang="en" ng-app="testApp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Sample</title>
<style>
.starter-template {
padding: 10px 15px;
text-align: center;
}
a {
font-size: 11px;
cursor: pointer;
}
</style>
</head>
<body>
<div ng-controller="mainCtrl">
<div class="container">
<div class="starter-template">
<h1>Example</h1>
<p class="lead">{{test}}</p>
<my-bootstrap-drop-down
my-label="Some label"
my-options="dropDownOptions"
my-function="runThis" >
</my-bootstrap-drop-down>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="app.js"></script>
</body>
</html>
Обратите внимание на «() (val)» в контроллере директив. Если вам не нужно передавать какое-либо значение обратно в исходный контроллер, просто замените его на «() ()».
Надеюсь, это поможет, если вы все еще застряли, вам следует поделиться большей частью своего кода (например, кодом вашей директивы и html), чтобы мы могли лучше ответить.
Похожие вопросы
Новые вопросы
angularjs
Используйте для вопросов об AngularJS (1.x), JavaScript-фреймворке с открытым исходным кодом. НЕ используйте этот тег для Angular 2 или более поздних версий; вместо этого используйте тег [angular].