AngularJS在ng-repeat生成的元素中传递变量参数函数调用

时间:2018-09-23 08:13:42

标签: angularjs

如果需要在组件中封装内部Bootstrap元素,则无法将Bootstrap与AngularJS组件一起使用,因为组件本身的额外标记添加到DOM中,直接子运算符>破坏了CSS规则。例如,实现DropDown时需要使用DropDown创建一个完整的组件,并应使用ng-repeat从配置数组中读取数据来在该完整的组件内生成每个dropdown选项。像这样:

<my-bootstrap-drop-down 
    my-label="Some label" 
    my-options="[ { label: 'Option1 },  {label: 'Option2'} ]" >
</my-bootstrap-drop-down> 

要从Dan Wahlin's "Creating Custom AngularJS Directives"传递参数到变量的函数到AngularJS组件,您需要一种特殊的语法,在该函数中,将函数引用传递给element标签的属性是这样的:

<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 :(得分:1)

编辑: 好的,不确定为什么需要此功能,但我可以使用它: https://plnkr.co/edit/uR9s5vUJxQoviTiUD2vj?p=preview

相同,但使用指令: https://plnkr.co/edit/Onh2WonmarpUscnFFLGK?p=preview

编辑结束

您应该将变量传递给“ my-options”(我们称其为“ dropDownOptions”):

GrantedAuthority

dropDownOptions数组应包含指令中所需的数据,但仅包含数据,而不是函数:<my-bootstrap-drop-down my-label="Some label" my-options="dropDownOptions" > </my-bootstrap-drop-down>

现在,在您的指令内,您可以访问数据并可以在操作/功能部分工作。示例:

[{"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>'
    };
});

在指令的控制器中注意“()(val)”。如果您不需要将任何值传递回原始控制器,只需将其替换为“()()”即可。

希望这对您有帮助,如果您仍然遇到问题,应该共享更多代码(例如您指令的代码和html),以便我们更好地回答。