Reputation: 390
We are implementing reusable code in our application for this purpose we have created a simple directive which displays content.
Directive Code:
angular.module("newsStore.moduleDirectives", [])
.directive('renderAboutContent', ['aboutService', renderAboutContent]);
function renderAboutContent(aboutService) {
return {
restrict: 'AE',
scope: {},
templateUrl: 'templates/about.html',
link: function (scope, element) {
aboutService.getAboutContent()
.then(function (results) {
scope.aboutList = results.aboutContent.listItems;
}, function (error) {
console.log('controller error', error);
});
}
}
}
HTML code:
<div class="col-md-12 aboutUs-ph padT10 content-ph_abt" ng-repeat="content in aboutList">
<div class="col-md-2 form-group" ng-if="content.image">
<img src="{{content.image}}" class="img-responsive" />
</div>
<div class="col-md-9">
<span class="guidedTourText"><b>{{content.title}}</b></span>
<br>
<span>{{content.description}}</span>
</div>
</div>
Question:
In the above HTML you can see col-md-2 and col-md-9 inside col-md-12, let's say I have three div elements, and three of them occupies 4, 4 ,4 if the content is present. Let's say if the content is not present in the last div then the remaining two div's should take 6,6 and vice versa. We want this to be implemented from the directive.
Let me know if I am not clear.
Upvotes: 1
Views: 3003
Reputation: 52847
I would set up a $watch inside of your link function. The $watch would monitor a function, and that function would look for DOM changes (i.e. DIV children changes). Depending on the state of the DOM, then dynamically add the col-* attributes
Directive
app.directive('bootstrapColumns', function() {
return {
restrict: 'A',
link: function(scope, element, attr) {
if (!element.hasClass('row'))
element.addClass('row');
scope.$watch(function() {
var elems = element[0].childNodes;
var count =0;
angular.forEach(elems, function(e) {
if (e.tagName == 'DIV' && angular.element(e).text() != '')
++count;
});
return count;
},
function(cols) {
var colNum = 12 / cols;
var cssClass = 'col-xs-' + colNum;
var elems = element[0].childNodes;
angular.forEach(elems, function(e) {
if (e.tagName == 'DIV') {
var div = angular.element(e);
if (div.text() != '' && !div.hasClass(cssClass))
div.addClass(cssClass);
}
});
});
}
}
});
HTML
<div bootstrap-columns>
<div>Column1</div>
<div>Column2</div>
</div>
Upvotes: 1
Reputation: 39287
As a follow up to using ng-class
, you can also use a function that returns the class:
var app = angular.module('app', []);
app.directive('aboutDirective', function renderAboutContent(aboutService) {
return {
restrict: 'AE',
scope: {},
templateUrl: 'about.html',
link: function(scope, element) {
aboutService.getAboutContent()
.then(function(results) {
scope.aboutList = results.aboutContent.listItems;
}, function(error) {
console.log('controller error', error);
});
scope.colWidth = function(content) {
return content.image && content.something ? 'col-xs-4' : 'col-xs-6';
}
}
}
});
app.factory('aboutService', function($timeout) {
return {
getAboutContent: function() {
return $timeout(function() {
return {
aboutContent: {
listItems: [{
image: 'image1',
title: 'title1',
description: 'desc1',
something: 'something1'
}, {
image: 'image2',
title: 'title2',
description: 'desc2'
}, {
title: 'title3',
description: 'desc3',
something: 'something3'
}]
}
};
}, 1000);
}
};
});
.row {
display: flex;
text-align: center;
color: #fff;
}
.image {
background-color: #75b5aa;
border: 1px solid #000;
}
.middle {
background-color: #aa759f;
border: 1px solid #000;
}
.something {
background-color: #6a9fb5;
border: 1px solid #000;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/js/bootstrap.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.css">
<div class="container" ng-app='app'>
<about-directive></about-directive>
<script type="text/ng-template" id="about.html">
<div class="row" ng-repeat="content in aboutList">
<div ng-if="content.image" class="image" ng-class="colWidth(content)">
{{ content.image }}
</div>
<div class="middle" ng-class="colWidth(content)">
<span><b>{{content.title}}</b></span>
<br>
<span>{{content.description}}</span>
</div>
<div ng-if="content.something" class="something" ng-class="colWidth(content)">
{{content.something}}
</div>
</div>
</script>
</div>
Upvotes: 1
Reputation: 25797
I'm giving you a generic usage, you can easily write it with your content. Suppose you have three variables available in your scope: content
, content2
and content3
. Now you can write like this:
<div class="row">
<div class="col-md-6" ng-class="{'col-md-4': content3}">{{content1}}</div>
<div class="col-md-6" ng-class="{'col-md-4': content3}">{{content2}}</div>
<div class="col-md-4" ng-show="content3">{{content3}}</div>
</div>
So what is happening here is, by default the col-md-6
will be given to the columns and if there is there is content in the 3rd column then we will also the class col-md-4
so that all three columns can be equally divided. col-md-4
will take precedence over col-md-6
.
Or, if you want more clearance, you can simply write this also:
<div class="row">
<div ng-class="{'col-md-4': content3, 'col-md-6': !content3}">{{content1}}</div>
<div ng-class="{'col-md-4': content3, 'col-md-6': !content3}">{{content2}}</div>
<div class="col-md-4" ng-show="content3">{{content3}}</div>
</div>
Upvotes: 1