Angular JS Directive - Template, compile or link?

大憨熊 提交于 2019-12-19 22:07:15

问题


I would like to create an Angular JS directive to check the length of a string, if it is too long to shorten it using a Filter, and show an Angular-UI popover on mouseover.

Where in the directive should I be placing the functionality to get this to work (link, template or compile)?

The view:

<div myapp-shorten="project">{{project.Description}}</div>

Here are my first attempts at the directive so far:

angular.module('myapp.directives', [])
 .directive('myappShorten', function () {

    function link(scope, element, attrs) {

        var outputText = "";

        if (myappShorten.Description.length > 20) {
            outputText += "<div popover='{{myappShorten.Description}}' popover-trigger='mouseenter'>" +
            "{{myappShorten.Description | cut:true:20:' ...'}}</div>";
        } else {
            outputText += "<div>{{myappShorten.Description}}</div>";
        }

        element.text(outputText);
    }

    return {
        link: link,
        scope: {
            myappShorten: "="
        }
    };

});

回答1:


First of all you can change the filter that it wouldn't alter string if it doesn't need to

Second, since you only need filter and popover - template is enough.

 angular.module('myapp.directives', [])
   .directive('myappShorten', function () {

     return { 
       scope: { data : '=myappShorten',
       template:"<div popover='{{data.Description}}' popover-trigger='mouseenter'>" +
        "{{ data.Description | cut:true:20:' ...' }}</div>"
     }
   })

Alternatively you can use combination of ng-show and ng-hide

 app.directive('shorten', function () {
return {
    restrict: 'A'
    , scope :  {
        shorten : '=',
        thestring: '='   
    }
    , template: "<div ng-show='sCtrl.isLong()' tooltip='{{ sCtrl.str }}'>{{ sCtrl.short() }}</div>"+
                "<div ng-hide='sCtrl.isLong()'>{{ sCtrl.str }}</div>"

    , controllerAs: 'sCtrl'
    , controller: function ($scope) {
        this.str = $scope.shorten || ''
        this.length = $scope.thestring || 20

        this.isLong = function() {
            return this.str.length > this.length   
        }

        this.short = function() {
            if ( this.str.length > this.length)  {
                return this.str.substring(0,this.length)  + '...'                    
            }
        }                                  
    }                               
  }       
})

Third option would be to actually use compile and $watch on myappShrten.Description but it seems to be overkill to me.




回答2:


The above accepted answer works fine. But if the value of thestring changes this will not update as the controller compiles on first run and then will not update if the value changes. Putting code into the controller compiles upfront, but putting the code in the link function allows it to update if the value changes. This is my preferred solution inspired by the solution above:

The view:

<shorten thestring="project.Description" thelength="40"></shorten>

The directive:

.directive('shorten', function () {
    return {
        restrict: 'E'
        , scope: {
            thelength: '=',
            thestring: '='
        }
        , link: function postLink(scope, iElement, iAttrs) {
            scope.isLong = function () {
                return scope.thestring.length > scope.thelength
            }

            scope.short = function () {
                if (scope.thestring.length > scope.thelength) {
                    return scope.thestring.substring(0, scope.thelength) + '...'
                }
            }

        }

        , template: "<div class='handCursor' ng-show='isLong()' tooltip='{{ thestring }}'>{{ short() }}</div>" +
                    "<div ng-hide='isLong()'>{{ thestring }}</div>"
    }
});


来源:https://stackoverflow.com/questions/23770882/angular-js-directive-template-compile-or-link

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!