AngularJS 将带有动态参数的函数传递给指令

AngularJS pass function with dynamic parameter to directive

TL;DR 版本:我正在尝试编写一个指令以在 table 中显示各种对象,并在 table 行的末尾添加一个编辑/删除按钮。

示例实体将为 ProjectType,因此:

项目-type.controller.js

    // determines which attributes we want to show in the table
    $scope.attr = [
        'computerName',
        'shortName',
        'longName'
    ];

    // puts the current projectType object to the form
    $scope.edit = function(projectType) {
        $scope.projectType = projectType;
        $scope.computerName = projectType.computerName;
        $scope.isEdit = true;
    };

    // shows a delete modal window
    $scope.deleteConfirm = function (projectType) {
        Modal.confirm.deleteModal('Project type', projectType.computerName, function () {
            Message.createMessage('project-type.message.delete.success', { projectType: projectType.computerName }, { type: 'warning', timeout: 4000 });

            $scope.remove(projectType);
        })();
    };

项目-type.html

    <!-- show table with directive -->
    <entity-table object="projectTypes" entity="'project-type'" attr="attr"></entity-table>

    <!-- show table without directive -->          
    <table class="table table-responsive">
        <thead>
        <tr>
            <th>{{ 'project-type.create.label.computerName' | translate }}</th>
            <th>{{ 'project-type.create.label.shortName' | translate }}</th>
            <th>{{ 'project-type.create.label.longName' | translate }}</th>
            <th>{{ 'common.operations' | translate }}</th>
        </tr>
        </thead>

        <tbody>
        <tr ng-repeat="projectType in projectTypes">
            <td><strong>{{ projectType.computerName }}</strong></td>
            <td>{{ projectType.shortName }}</td>
            <td>{{ projectType.longName }}</td>
            <td>
                <a ng-click="edit(projectType)" class="pencil"><span class="glyphicon glyphicon-pencil"></span></a>
                <a ng-click="deleteConfirm(projectType)" class="trash"><span class="glyphicon glyphicon-trash"></span></a>
            </td>
        </tr>
        </tbody>
    </table>

实体-table.directive.js

angular.module('unioffice-centralApp')
.directive('entityTable', function () {
    return {
        restrict: 'E',
        replace: true,
        transclude : true,
        templateUrl: '/components/directives/entity-table/entity-table.html',
        scope: {
            object: '=',
            entity: '=',
            attr: '='
        },
        link: function (scope, element, attrs, controllers, transclude) {
            console.log(scope);
        }
    };
});

实体-table.html

<div>
<table class="table table-responsive">
    <thead>
    <tr>
        <th ng-repeat="att in attr">{{ (entity + ".table.label." + att) | translate }}</th>
        <th ng-repeat-end translate>common.operations</th>
    </tr>
    </thead>

    <tbody>
        <tr ng-repeat="obj in object">
            <td ng-repeat="att in attr">{{ obj[att] }}</td>
            <td ng-repeat-end>
                <a ng-click="edit(obj)" class="pencil"><span class="glyphicon glyphicon-pencil"></span></a>
                <a ng-click="deleteConfirm(obj)" class="trash"><span class="glyphicon glyphicon-trash"></span></a>
            </td>
        </tr>
    </tbody>
</table>

(实体末尾有个/div-table.html,Whosebug好像把它干掉了)

所以问题是:如何将 edit() 和 deleteConfirm() 函数传递给指令以使其工作?

在这张图片中你可以看到两个 table 是一样的,但是第一个的按钮此时显然不会做任何事情:(我也知道第二个的第一个是粗体专栏,没关系,现在不是重点)

Passing/binding 从控制器到指令的功能与绑定对象 = 或字符串 @ 的方式相同,区别在于它在指令

将函数作为属性传递到指令中,如下所示..

<entity-table object="projectTypes" entity="'project-type'" on-delete="deleteConfirm" on-edit="edit" attr="attr"></entity-table>

在你的指令中这样做..

angular.module('unioffice-centralApp')
.directive('entityTable', function () {
    return {
        restrict: 'E',
        replace: true,
        transclude : true,
        templateUrl: '/components/directives/entity-table/entity-table.html',
        scope: {
            object: '=',
            entity: '=',
            attr: '=',
            onDelete: '&', // function referencing
            onEdit: '&' // function referencing
        },
        link: function (scope, element, attrs, controllers, transclude) {
            scope.deleteFn = function (obj) {
                scope.onDelete()(obj); // this invokes the deleteConfirm function in the controller
            }

            scope.editFn = function (obj) {
                scope.onEdit()(obj); // this invokes the deleteConfirm function in the controller
            }
        }
    };
});

在你的控制器中...

$scope.edit = function(projectType) {
    $scope.projectType = projectType;
    $scope.computerName = projectType.computerName;
    $scope.isEdit = true;
};

// shows a delete modal window
$scope.deleteConfirm = function (projectType) {
    Modal.confirm.deleteModal('Project type', projectType.computerName, function () {
        Message.createMessage('project-type.message.delete.success', { projectType: projectType.computerName }, { type: 'warning', timeout: 4000 });

        $scope.remove(projectType);
    })();
};

PLUNKR