简体   繁体   中英

How to modify the individual scope of each element created by ng-repeat in a directive?

I'm trying to write a directive to simplify tables in Angular. I just want the user to provide the directive with the list object and the formatting of each list element in the html, like the my-table tag below...

<h3>My Table</h3>
<div ng-controller='Ctrl as ctrl'>
<my-table items=ctrl.list>
    title: {{$item.title}}
    name: {{$item.name}}
</my-table>
</div> 

I've got something working so far with the answer here but I need to add further functionality and I'm running into problems. In the my-table directive below you can see the html template in the link function. How can I set a variable on the individual scope of each list element? I should be able to modifiy it when the mouse hovers over that element (using ng-mouseenter and ng-mouseleave )? And I should be able to pass it to the table-edit-panel directive that I've referenced in the template...

(function() {
    'use strict';

    angular
        .module('myApp')
        .directive('myTable', myTable);

    myTable.$inject = ['$compile'];

    function myTable($compile) {
        var directive = {
            transclude: true,
            scope: {    
                items: '='            
            },
            link: link  
        };
        return directive;

        function link(scope, elem, attr, ctrl, transclude) {

            scope.onMouseLeave = function(testvar) {
                testvar.state = "ready";
            };

            scope.onMouseEnter = function(testvar) {        
                testvar.state = "active";           
            };

            // not working, seems to be only one testvar rather than one for each element
            var template = 
                '<div ng-repeat="$item in items" ng-mouseenter="onMouseEnter(testvar)" ng-mouseleave="onMouseLeave(testvar)">' +
                    '<div class="row">' +                   
                    '<div class="col-md-10">' +
                        '<placeholder></placeholder>' +
                    '</div>' + 
                    '<div class="col-md-2">' +
                        '<table-edit-panel value="testvar"></table-edit-panel>' +
                    '</div>' +
                    '</div><hr/>' +
                '</div>';               

            var templateEl = angular.element(template);

            transclude(scope, function(clonedContent){
                templateEl.find("placeholder").replaceWith(clonedContent);

                $compile(templateEl)(scope, function(clonedTemplate){
                    scope.testvar = { state: "ready" }; // should be a testvar for each element of the list!
                    elem.append(clonedTemplate);
                });
            });
        }
    }
})();

You can access the complete code on the jsfiddle . You can see the problem is that with my current approach, when I hover over one list element the testvar variable changes for all the list elements rather than the one I hovered over.

Using $item.testvar instead of testvar, you can access the sub-scope of each item.

 var template = '<div ng-repeat="$item in items" ng-init="$item.testvar.state = \'ready\'" ng-mouseenter="onMouseEnter($item.testvar)" ng-mouseleave="onMouseLeave($item.testvar)">' +
    '<div class="row">' +                   
    '<div class="col-md-10">' +
        '<placeholder></placeholder>' +
    '</div>' + 
    '<div class="col-md-2">' +
        '<table-edit-panel value="$item.testvar"></table-edit-panel>' +
    '</div>' +
    '</div><hr/>' +
'</div>';   

However these state variables needed to be initialized in this scenario. I added an ng-init to achieve this. While this is one of the few intended uses for ng-init, it is in my opinion cleaner to initialize the state variables in your controller.

var template = 
    '<div ng-repeat="$item in items" ng-init="testvar.state = \'ready\'" ng-mouseenter="onMouseEnter(testvar)" ng-mouseleave="onMouseLeave(testvar)">' +
    '<div class="row">' +                   
    '<div class="col-md-10">' +
        '<placeholder></placeholder>' +
    '</div>' + 
    '<div class="col-md-2">' +
        '<table-edit-panel value="testvar"></table-edit-panel>' +
    '</div>' +
    '</div><hr/>' +
'</div>'; 

var templateEl = angular.element(template);

    transclude(scope, function(clonedContent){
        templateEl.find("placeholder").replaceWith(clonedContent);

        $compile(templateEl)(scope, function(clonedTemplate){

            // REMOVED THIS LINE:
            // scope.testvar = { state: "ready" };
            elem.append(clonedTemplate);

        });
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM