Hi,
I am building feeds like pinterest, having cards with different data and different permissions, structure is something like this :

(1)Main directive structure
(1.1)can have image,video,audio
(1.2)some permissions like (edit,delete,hide)

also having infinite scroll, so the structure I made is something like this
<ul>
<li ng-repeat="cardsInfo in feeds">
<my-card-directive card-data="{{cardsInfo.type}}" media-feed-type="{{cardsInfo.feed_type}}" card-id="{{$index}}"></my-card-directive>
</li>
</ul>
.directive('myCardDirective', ['$compile', '$templateRequest', function($compile, $templateRequest) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
function uploadTemplate(templateName) {
$templateRequest('templates/home/templates/feedCards/' + templateName).then(function(html) {
var template = angular.element(html);
elem.html($compile(template)(scope));
})
}
switch (attrs.cardData) {
case 'type1':
uploadTemplate('type1.html')
break;
case 'type2':
uploadTemplate('type2.html')
break;
case 'type3':
if (attrs.mediaFeedType == '') {
uploadTemplate('type3.html');
} else {
uploadTemplate('type3_1.html');
}
break;
case 'type4':
case 'type5':
uploadTemplate('type4.html');
break;
case 'type5':
case 'type6':
case 'type7':
uploadTemplate('type5.html')
break;
case 'type8':
uploadTemplate('type6.html')
break;
case 'type9':
uploadTemplate('type7.html');
break;
default:
uploadTemplate('default.html')
break;
}
}
}
}])
'type(anynumber).html' contains
<!-- inner directve 1 -->
<figure check-media-type media="{{cardsInfo.file_type}}">
<third-party-video ng-if="on-some-condiition"><third-party-video>
</figure>
<!-- some filters and other info -->
<div class="foot">
<!-- some footer styles -->
<!-- inner directive 2 -->
<div class="dropdown-menu dropdown-menu-default" check-feed-card owner-detail="{{cardsInfo.ownerPermission}}" content-type="{{cardsInfo.content_type}}"></div>
</div>
</div>
</div>
</div>
<!-- inner directive 1 definition-->
.directive('checkMediaType', ['$compile', function($compile, filter) {
return {
restrict: 'A',
link: function(scope, elem, attrs) {
var embedUrl = angular.element('<third-paty-embed-video controls="1" width="100%" ></third-party-embed-video>');
var addImage = angular.element('<img alt="" />');
var addAudio = angular.element('<audio controls><source type="audio/ogg"></audio>');
switch (attrs.media) {
case 'image':
var imgsrc = thumbnail(attrs.mediaFile)
addImage.attr('src', imgsrc);
elem.html($compile(addImage)(scope));
break;
case 'video':
if ('some_conditions_check') {
embedUrl.attr('data-ng-href', attrs.isEmbed);
elem.html($compile(embedUrl)(scope));
}
break;
case 'audio':
break;
case '':
embedUrl.attr('data-ng-href', attrs.isEmbed);
elem.html($compile(embedUrl)(scope));
break;
}
}
}
}])
<!-- inner directive 2 definition-->
.directive('checkFeedCard', ['[some services injected]', '$compile', function([services injected], $compile) {
return {
restrict: 'A',
replace: true,
transclude: true,
link: function(scope, elem, attrs) {
scope.setName;
var details = JSON.parse(attrs.ownerDetail);
var editMyPost = angular.element('<p class="set-p-margin"><a href="">Edit this {{setName}}</a></p>');
var deleteMyPost = angular.element('<p class="set-p-margin"><a href="" ng-click="Deletethis(cardsInfo,$index)">Delete this {{setName}}</a></p>');
var otherPosts = angular.element('<p class="set-p-margin"><a href="" ng-click="hideFeeds(cards)">Hide feeds from this {{setName}}</a></p>');
var userRedirectState;
var allowDeleteMyPost = false;
if (some_condition_checks) {
switch (attrs.contentType) {
case 'type-1':
userRedirectState = "type-1-RedirectStateAdded";
scope.setName = attrs.contentType;
break;
case 'type-2':
userRedirectState = 'type-2-RedirectStateAdded'
scope.setName = attrs.contentType;
break;
case 'type-3':
userRedirectState = 'type-3-RedirectStateAdded'
scope.setName = attrs.contentType;
break;
.
.
.
.
.
case 'type-n':
scope.setName = attrs.contentType;
userRedirectState = 'type-N-RedirectStateAdded';
break;
}
editMyPost.children(":first").attr('ui-sref', userRedirectState);
elem.html($compile(editMyPost)(scope));
if (allowDeleteMyPost) {
elem.append($compile(deleteMyPost)(scope));
allowDeleteMyPost = false;
}
} else {
scope.setName = detectUser.detectUserType(details.user_type);
if (some_condition_checks) {
elem.html($compile(otherPosts)(scope));
}
}
}
}
}])
Problem: In initial cases when feeds were few(especially images), all were good, no lags but as soon number increased with variety of data (audio, video,embedded url's) it's showing heavy lag with application got crashed in few feeds only (around 40-50), when checked for watchers it showed around 3k watchers, which is definitely wrong.

Is $compile cost heavy for such a case? because of infinite scroll fetching more data. Any valuable suggestion for performance can be improved or in approach. My approach was to divide it into different independent components, may be I have not used $compile properly or is it excessive usage in this scenario.
PS : I also tried to change all 2-way binding to single binding, which are only to display information.
using this library for grid generation : ignitersworld.com/lab/angulargrid
Thanks.
Its the problem where you should look at one way binding / reducing bindings. One of the best way to use two way binding with a huge data is virtual repeat. I have kind of same problem in my application, where i have around 10k rows with 13-18 columns which have 2-4 different components which needs two way binding. There are many virtual repeat directives if you google them, however i am using
md-virtual-repeatby Angular Material. The one problem it can create for you that virtual repeat requires all item height to be equivalent, so if you have a row of 10px then all rows should be 10px. The only dark side of this, rather then this it works smoothly. I saw that google fonts have kind of same thing on their new home page which does the same thing. The logic behind virtual repeat is pretty simple, imagine you have a wrapper of 250px and have 100 items 5px each, now you have items worth 500px and viewarea is 250px what virtual repeat will do is when you scroll in your container, it only loads that items which can be visible in that 250px area ( 2/3 extra to maintain smooth scrolling )I am not sure if the Material design one will work for your issue, however you can write a custom one which can work with dynamic heights :)