Using an AngularJS directive to dynamically incorporate Bootstrap classes in the HTML elements

Our application is now incorporating reusable code by creating a simple directive to display content efficiently.

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:

The HTML code above shows col-md-2 and col-md-9 inside col-md-12. If there are three div elements with content occupying 4, 4, 4 respectively, but the last one has no content, we want the remaining two divs to take up 6 each instead of 4. This behavior needs to be implemented through the directive.

Please let me know if I need to clarify anything further.

Answer №1

To implement dynamic column sizing in Bootstrap, you can create a custom directive that watches for changes in the DOM structure and then adds corresponding Bootstrap classes.

Custom 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);
                    }
                });
            });
        }
    }
});

Usage in HTML

<div bootstrap-columns>
   <div>Column1</div>
   <div>Column2</div>  
</div>

Check out the demo on JSFiddle

Answer №2

Providing a generic example for usage, allowing you to customize it with your own content. Let's say you have three variables accessible in your scope: content, content2, and content3. Here is an example of how you can use them:

<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>

By default, the columns will have a width of col-md-6, but if there is content in the 3rd column, then the class col-md-4 will also be applied to ensure equal division among all three columns. The col-md-4 class takes priority over col-md-6.

Alternatively, for more clarity, you can utilize this structure as well:

<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>

Answer №3

After utilizing ng-class, you have the option to implement a function that will determine 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

implementing multiple updates in Mongoose for MongoDB

There are often times when I need to make multiple update requests based on various conditions. if (some true condition) { let recordBeforeUpdate = await this.PatchModel.findOneAndUpdate({ "_id": patchId }, { $inc: { inStockPallets: -1, f ...

How can I determine the remaining amount of scroll left in my HTML document?

Is there a method to determine how many pixels of scroll remain on the page when the scrollbar is set at a specific position? I am currently utilizing jQuery's scrollLeft feature, which can be found here: http://api.jquery.com/scrollLeft/. I want to ...

What is the best way to add an insert button to every row?

Take a look at the image provided. When I click on any register button, the last row is being inserted instead of the desired row. What I'm aiming for is this: when I click register, the entire selected row should be stored in a separate table. Whe ...

What is the best way to send extra parameters to an ajax callback function?

Currently, I am implementing an ajax call in the following manner: util.AjaxCall(url, successCallbackFunction, errorCallbackFunction); function successCallbackFunction(result) { // Result returned from Ajax } Although everything is functioning correc ...

Is it possible to implement PortalVue in multiple Vue.js single file components?

While working on Vue.js (single file components), I have discovered three methods of passing data around: local state/props, store, and utilizing PortalVue. Through my experiments with PortalVue, I successfully implemented both portal and portal-target wit ...

Is it possible to refresh HTML content using jQuery?

Currently, I am attempting to iterate through response data and integrate the values into the HTML of my webpage. It's crucial for me to clear any existing values in the HTML so that only the new ones are displayed, keeping it up-to-date. The structu ...

Different ways to provide user feedback on a SPA website following AJAX requests

I have a single-page application website developed using React.js. What are some options for notifying the user of successful/failed/pending AJAX calls resulting from various user interactions? I am aware of Toastr-style messages that appear in the corner ...

Steps for including a subdocument within a mongoose schema

I am currently working on setting up a subdocument within a mongoose schema using node.js/Express. There are two schemas in play: Member and Address Member.js // app/models/member.js // Loading mongoose to define the model var mongoose = require(' ...

Error Encountered During JavaScript Form Validation

Currently, I am troubleshooting a website that was created by another developer. There is a form with JavaScript validation to ensure data is accurately entered into the database. However, I am puzzled as to why I keep receiving these alert messages. Pleas ...

Angular encountered a 403 error while making an HTTP POST request

After successfully implementing angularJS validation in my form on localhost, I encountered a 403 Error (Forbidden) on line 72 of my angular.min.js file when trying to upload the code to my web server. I have tried numerous solutions but remain stuck on t ...

Achiever.js - Incorporating incremental progress with half stars instead of whole stars

Hello there! I've been utilizing Rater.js in my current project, and so far it has provided me with satisfactory results. However, I have encountered a particular issue that I am struggling to resolve on my own. It would be greatly appreciated if you ...

Memory leakage in Internet Explorer as a result of JavaScript code

Recently, I created a website that utilizes jquery ajax to send an ajax request every minute in order to retrieve json data. This data is then parsed and added into the DOM. While this process runs smoothly on Chrome and Firefox, I noticed a significant m ...

Fancybox operates successfully when I manually include a class, yet fails to function when utilizing jQuery's .addClass() method

Below is a snippet of JS code that I use to add Fancybox classes to all hrefs on a webpage: $(function(){ //declaring target variable var $targetTable = $('.photo-frame a'); //looping through each table and adding the fancybox cla ...

Using Angular's ng-repeat directive to iterate over an array from JavaScript

I am attempting to display an array in the HTML HTML: <div class="personWrapper" ng-repeat="message in messages"> <p>{{message}}</p> </div> JS: var app = angular.module('matcherApp', [ "ngRoute", "ngStorage" ] ...

React JS is not allowing me to enter any text into the input fields despite my attempts to remove the value props

Currently, I am working on creating a Contact Form using React Js. I have utilized react bootstrap to build the component, but unfortunately, when attempting to type in the input fields, the text does not change at all. import React, {useState} from ' ...

What is the process of using an if statement in jQuery to verify the existence of a property in a JSON file?

I am working on a task to incorporate an if statement that checks for the existence of a specific property in a JSON file. If the property exists, I need to display its value within HTML tags <div class='titleHolder'> and "<div class=&ap ...

Ordering ng-repeat in AngularJS using a separate arrayDiscover how to easily order your

Imagine I have an array containing keys in a specific order orderedItems=["apple","banana","orange]; and there is a JSON object that I want to display using ng-repeat but following the sequence specified in the array: {"fruits": { "apple":{ ...

Latest News: The store is now received in the mutation, instead of the state

An update has been made to this post, please refer to the first answer After thorough research, I couldn't find a solution to my issue despite checking several threads. This is my first time using the Quasar framework and it seems like I might have o ...

If the Request does not recognize the OAuth key, generate a fresh new key

I am working with a React Native Frontend and an Express.js backend. The backend makes calls to a 3rd party API, which requires providing an OAuth key for the user that expires every 2 hours. Occasionally, when calling the API, I receive a 400 error indi ...

using node.js to save query results as global variables

Help needed! I'm struggling to pass the results of my query statement to a global variable in order to dynamically configure my jsganntimproved chart. Any suggestions on what could be going wrong? In the snippet below, the console.log(taskItem) retur ...