limitTo in Angularjs
I have been using Angular 1.x for sometime. limitTo filter allows you to truncate a given input. limtTo takes a numeric parameter that defines, what length of input string you want to keep when this filter is applied. The limitTo however doesn’t work properly when you have a HTML embedded with in the string.
I have read multiple implementations for solving this issue. One of the implementation was to create a new filter that omits HTML using regular expressions and then size it as per the requested length. Using this approach was working but we were loosing all embedded HTML in the string that was truncated.
I applied below given solution that works well. In our case it needed to truncate various categories of RSS feed upto 400 characters.
Custom Directive
The below given custom directive was to show news categories. Each category was picked from an RSS feed and was passed to this directive.
News.js
(function() { 'use strict'; angular.module('demoApplication') .directive('demoNews', function() { return { restrict: 'E', transclude: true, replace: true, scope: { caseStudy: '=', blog: '=', news: '=' }, templateUrl: "shared/news/news.html", controller: ['$scope', 'ControllerFactory', '$filter', '$sce', function($scope, ControllerFactory, $filter, $sce) { var filterData = function(content, size) { if (content) { var contentFiltered = content; if (content.length > size) { contentFiltered = $filter('limitTo')(content, size - 3) + "..."; } return $sce.trustAsHtml(contentFiltered); } }; /** * News content filtered and html applied **/ $scope.newsContent = function() { if ($scope.news && $scope.news.content) { return filterData($scope.news.content, 400); } }; /** * Blog content filtered and html applied **/ $scope.blogContent = function() { if ($scope.blog && $scope.blog.content) { return filterData($scope.blog.content, 1000); } }; /** * Case Study content filtered and html applied **/ $scope.caseStudyContent = function() { if ($scope.caseStudy && $scope.caseStudy.content) { return filterData($scope.caseStudy.content, 4000); } }; }] }; }); })();
The above Angular code is declaring a directive. This directive allows news, caseStudy and blog information to be passed, this information is displayed on news.html file. Please note that the data set in these scope variables contain html tags. There are three functions to provide a truncated html content to news.html.
News.html file refer to these functions mainly newContent, blogContent and caseStudyContent. These functions perform a truncation on incoming string content with a different length need. If the required length is more than the scope variable length same string is returned else a limitTo filter is applied and an ellipsis is appended.
Once filter is applied $sce is used to send resulting string to display as html on view.
News.html
<div class="row seperator home-articles" style="margin:60px 0px;"> <div class="container"> <!-- Latest News --> <div class="col-md-4 col-xs-12"> <div class="home-latest-news"> <h3 class="news-head"><span class="text">Latest News</span> <p class="space"> </p></h3> <div class="clear"></div> <h4 class="news-title">{{news.title}}</h4> <div ng-bind-html="newsContent()"></div> <a ng-show="news.link" href="{{news.link}}" class="colored-link">Learn More</a> </div> </div> <!-- Latest Post --> <div class="col-md-4 col-xs-12"> <div class="home-latest-news"> <h3 class="news-head"><span class="text">Latest Post</span> <p class="space"> </p></h3> <div class="clear"></div> <h4 class="news-title">{{blog.title}}</h4> <div ng-bind-html="blogContent()"></div> <a ng-show="blog.link" href="{{blog.link}}" class="colored-link">Learn More</a> </div> </div> <!-- Upcoming Events --> <div class="col-md-4 col-xs-12"> <div class="home-latest-news"> <h3 class="news-head"><span class="text">Case Study</span> <p class="space"> </p></h3> <div class="clear"></div> <h4 class="news-title">{{caseStudy.title}}</h4> <div ng-bind-html="caseStudyContent()"></div> <a ng-show="caseStudy.link" href="{{caseStudy.link}}" class="colored-link">Learn More</a> </div> </div> </div> </div>