AngularJS передает переменные вызовы функции аргумента в элементах, созданных с помощью ng-repeat - PullRequest
0 голосов
/ 23 сентября 2018

Использование начальной загрузки с компонентами 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, но применять не разрешается в угловых выражениях.

Я добавил Plunker, чтобы прояснить это:

https://plnkr.co/edit/dkofEYhebp0T6lSf22RP?p=preview

1 Ответ

0 голосов
/ 24 сентября 2018

Редактировать: Хорошо, не уверен, зачем вам это нужно, но я заставил его работать: 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), чтобы мы могли ответить лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...