2

TL;DR version: I'm trying to write a directive to show various objects in a table, and add an edit / delete button at the end of the table rows.

The example entity will be ProjectType, so:

project-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);
        })();
    };

project-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>

entity-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);
        }
    };
});

entity-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>

(there is a /div at the end of the entity-table.html, stackoverflow seems to kill it)

So the question is: how do I pass the edit() and deleteConfirm() functions to the directive to make them work?

In this picture you can see the two tables are the same, but the buttons in the first one obviously won't do anything at this point: (also I know the second one has bold first column, it's ok, that's not the point now) screenshot

2
  • Is there any reason you don't want the deleteConfirm function in the directive instead of the controller? There is a way around but I'm just curious Commented Feb 10, 2015 at 12:09
  • Because the deleteConfirm() calls the remove(), than I would have to put that too into the directive, and those functions are entity-specific, they wouldn't work. Also I want to keep my business logic in the controller, and the view in the directive. Also what's the workaround you mentioned ? Commented Feb 10, 2015 at 12:35

1 Answer 1

4

Passing/binding the functions from the controller to the directive is done in the same manner as binding an object = or a string @ with the difference being how it's referenced in the directive

Pass in the functions as attributes on the directive as shown below ..

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

In your directive do this ..

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
            }
        }
    };
});

In your 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

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks brother, that was exactly what I was searching for. Accepted. (btw you have a small typo, in the scope.deleteFn item should be obj, but other than that, 100% working solution)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.