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 pile)?
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: "="
}
};
});
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 pile)?
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: "="
}
};
});
Share
Improve this question
edited Jan 15, 2016 at 13:31
vittore
17.6k6 gold badges46 silver badges84 bronze badges
asked May 20, 2014 at 22:16
Holland RisleyHolland Risley
6,7819 gold badges27 silver badges36 bronze badges
1
- Perhaps a more prehensive overview of directive functions: Angular directives - when to use pile, controller, pre-link and post-link. – Izhaki Commented Jul 7, 2014 at 16:41
2 Answers
Reset to default 4First 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 bination 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 pile and $watch on myappShrten.Description but it seems to be overkill to me.
The above accepted answer works fine. But if the value of thestring
changes this will not update as the controller piles on first run and then will not update if the value changes. Putting code into the controller
piles 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>"
}
});