Keep track of object ids properly after creating e

2019-08-25 00:29发布

问题:

I have created a list of items with an object inside my controller

$scope.devices = [
    {"id": 0, "name": "sw", "class": 'sw' },
    {"id": 1, "name": "mlr", "class": 'mlr'},
    {"id": 2, "name": "lvm", "class": 'lvm'},
    {"id": 3, "name": "ltc", "class": 'ltc'},
    {"id": 4, "name": "fr", "class": 'fr'},
    {"id": 5, "name": "cap", "class": 'cap'}
];

and ng-repeat in my HTML

<li ng-repeat="device in devices" ng-click="selected(device.id)"></li>

I can keep track of an item that is clicked with $scope.selected bound to my ng-click that's basic.

However, what about later on, in a directive when an even fires? How can I collect information from the element? Specifically the original object id it came from?

// A device is grabbed
ums.directive('draggable', function (){

return function ($scope, element, attr){
    // restrict: "A",
    // link: function (){}

    var el = element[0];
    el.draggable = true;

    el.addEventListener(
        'dragstart',
        function(e) {
            e.dataTransfer.effectAllowed = 'move';
            e.dataTransfer.setData('Text', this.id);
            this.classList.add('drag');

            // when this event is fired I want the corresponding object id from $scope.devices
            console.log(el.$scope.device.id); // my first inclination

            return false;
        },
        false
    );

}

})

回答1:

The ng-repeat directive creates a scope for each line that it adds to the DOM. On each scope will be special properties set by ng-repeat.

From the Docs:

The ngRepeat directive instantiates a template once per item from a collection. Each template instance gets its own scope, where the given loop variable is set to the current collection item, and $index is set to the item index or key.

The scope inherits from $parent scope. In your directive's linking function, you can use scope.$parent.devices[scope.$index] to access the original but it is also on the local scope as well.

For more information see the AngularJS ngRepeat API Reference.

Update with example

This example shows the directive getting the $index and also emitting a custom event for the controller to use.

The directive

ums.directive('draggable', function (){
    function postLinkFn (scope, elem, attr){
        console.log("instantiating directive");

        elem.prop('draggable', true);

        elem.on ('dragstart',
            function(e) {
                elem.addClass('drag');
                console.log("dragstart index =", scope.$index);
                //emit event for controller
                scope.$emit("umsDragstart", e);
                return false;
            }
        );
    }
    return postLinkFn;
})

In the controller

    $scope.$on("umsDragstart", function ($event, rawEvent){ 
         console.log($event);
         console.log(rawEvent.x, rawEvent.y);
         console.log("umsDragstart id =", $event.targetScope.device.id);
    });

Notice that the example uses jqLite methods on the elem parameter of the postLinkFn. Those methods are documented in the AngularJS angular.element API Reference.

The $on and $emit methods are documented in the AngularJS $rootScope.scope API Reference - $on and API Reference - $emit.



回答2:

If you are using the directive inside the controller in which selected() function is written the you can assign the id to some scope variable and access it in directive. else if you are using the directive inside a ng-repeat then you can set custom scope variable for directive and pass the current id to it. or else give away a code example