Applying a CSS class (or style) dynamically depending on the variable with the help of a directive

I'm facing a situation where I need to apply ng-style (or ng-class) multiple times depending on a variable.

However, this repetitive task of writing ng-class for the same functionality for each widget is quite cumbersome for me.

Is there a way to simplify this process? I am aware that creating a custom directive could help achieve this, but my attempts so far have not been successful.

Below is an excerpt from my code:

<div class="panel panel-primary" ng-style="expanded1 ? {{'height': viewPortHeight} : ''" ng-click="expanded1=!expanded1">Panel 1</div>
..........
<div class="panel panel-primary" ng-style="expanded2 ? {{'height': viewPortHeight} : ''" ng-click="expanded2=!expanded2">Panel 2</div>

Is it possible to create a directive (C or A) that can detect the "expanded" variable for each specific element and apply the style accordingly?

I attempted to do this, but encountered difficulties.

== Custom Directive

(function (app) {
  app.directive('expandWidget', function() {
      return {
          restrict: 'A',
          link: function(scope, element, attrs) {
            scope.$watch('expanded', function(expanded){
                if(expanded)
                    element.css('height', 'viewPortHeight')
                else element.css('height', '300px')
            })
          }
      }
    })
})
<div class="panel panel-primary" expand-widget ng-click="expanded1=!expanded1">Panel 1</div>

I am open to exploring alternative approaches that can achieve the same goal as mentioned above.

Answer №1

Here is my take on solving your issue, I hope this solution works for you.

.directive('expandWidget', function() { return { restrict: 'A', link: function(scope, element, attrs) {

  var expanded = attrs['expanded'] === 'true' || false;
  var exapndedHeight = (attrs['exapndedHeight'] || 600) + 'px';
  var collapsedHeight = (attrs['collapsedHeight'] || 50) + 'px';

  function setHeight() {
    element[0].style.height = expanded ? exapndedHeight :  collapsedHeight;
  }

  function toggle() {
    expanded = !expanded
    setHeight();
  }

  element[0].addEventListener( attrs['trigger'] || 'click', toggle);
  setHeight();
}

} })

https://plnkr.co/edit/Hthl41G0dbZhk8v2BDFv

Answer №2

If you want to control a scope variable:

$scope.expanded = false;

You can pass it as an attribute to the directive:

<div class="panel panel-primary" 
   expand-widget 
   expanded="{{ expanded }}" 
   ng-click="expanded = !expanded">

Using attrs.$observe, you can monitor changes in the expanded attribute and take action with the element(s) accordingly:

.directive('expandWidget', function() {
  return {
    restrict: 'A',
    scope: {
      expanded: '@'  
    },
    link: function(scope, element, attrs) {
      attrs.$observe('expanded', function(expanded){
        expanded = expanded == 'true'
        if (expanded) { 
          element[0].style.height = '250px'
        } else {           
          element[0].style.height = '100px'
        }   
      })
    }    
  }
})

Demo -> http://plnkr.co/edit/0FHVGwQx7jogHyGol7fN?p=preview

$scope.expanded is just one example. If you have multiple panels, you could use:

$scope.panels = {
  expanded1: true,
  expanded2: false,
  expanded3: false
  ...
}

and manipulate $scope.panels.expanded2 instead. In the example code, I set an arbitrary height since I wasn't sure what "viewPortHeight" referred to.


If you prefer toggling classes over directly modifying styles, you can do this:

attrs.$observe('expanded', function(expanded){
   expanded = expanded == 'true'
   if (expanded) { 
     $(element)
       .removeClass('defaultClass')
       .addClass('expandedClass')
   } else {            
     $(element)
       .removeClass('expandedClass')
       .addClass('defaultClass')
   }   
})

Demo -> http://plnkr.co/edit/UZWPYoTOu0ABqnVqrmw3?p=preview

It's acceptable to utilize jQuery here since bootstrap is already being used.

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

Is there a Node template engine similar to EJS that seamlessly integrates with HTML templates?

Is there a template engine for NodeJS similar to EJS that doesn't alter the original HTML template structure with its use of parentheses? In EJS, one might utilize the following code snippet to embed specific data into the HTML template: <script& ...

Attempting to conditionally apply CSS to a component based on a prop, but unfortunately it is not functioning as expected

.storyMobile{ color:green; } .storyWeb{ color:red; } <div class="storyMobile"> hii </div> <div class="storyWeb"> hii </div> //main view <div> <story :story="stories[0]"/> </div> //here it prints ...

capturing the HTML title and storing it in a JavaScript variable

Is there a way to retrieve the title "Some Name" in the JS file and have it be populated by the hyperlink's title attribute, which is set to "sometitle" in the HTML code? JS var randomtext={ titleText:"Some Name",} HTML <a class="css" title="so ...

Adjust size of item within grid component in VueJS

I have a grid container with cells and a draggable item in a Vue project. I am trying to figure out how to resize the box inside the grid component (refer to images). https://i.stack.imgur.com/q4MKZ.png This is my current grid setup, and I would like the ...

Suggestions for retaining dynamically modified HTML content post-response

My registration form includes input fields for username, email, and more. I have implemented a script that validates the form upon clicking the submit button, turning labels red when fields are empty. However, the submit button is also configured to send a ...

Is it true that DOM objects in JavaScript are considered objects?

I've been searching for an official answer to this question, but it seems there is some confusion. Some people consider DOM objects to be JS objects, while others argue that they are different entities. What is the correct answer? If you search on Sta ...

Strategies for setting up the runtime dynamically for Nextjs API routes

After deploying my Next.js 13 app on Cloudflare Pages, I encountered an issue with the API routes. To address this, I had to export the runtime variable from each route in the following manner. export const runtime = "edge" During local developm ...

Implementing pagination with Django-REST and AngularJS

I successfully integrated my angularjs app with django-rest, but encountered a problem when implementing pagination. Below is the code for my restservice and controller: // restservices.js // API call for all images in an event services.factory('Imag ...

What is the best way to render a view, hide parameters from the URL, and pass data simultaneously?

In order to display the current view: statVars["sessions"] = userSessions; res.render("statsSessions", statVars); Nevertheless, I must find a way to hide the URL parameters from showing up in the browser's address bar (these parameters are sourced ...

Is there a way to deactivate the save button on a form field that shares the same label but has a different ng-model in AngularJS

I am new to coding and I have a form with multiple fields labeled as AGE, each with different ng-model and name attributes. My goal is to keep the save button disabled until all the Age fields are filled out. <table> <tbody> <tr> < ...

Refreshing the display in an AngularJS directive

I've developed a custom directive for handling file uploads in my AngularJS application. The directive is used in multiple places, including on the same page more than once. Each instance of the directive is supposed to display the uploaded file name ...

Switch between toggling tasks in Vue does not seem to be functioning as

I'm reaching out again because I'm struggling to figure out what I'm doing wrong. I followed a tutorial step by step but the code isn't working as expected. My goal is to toggle between marking tasks as done and not done. When I test th ...

Manipulating the InnerHTML content of a total of 144 individual cells

I am currently developing a tile-based game using tables. Each td cell contains the following code: <td> <div id="image" style="display:none; display: fixed; right: 5; top:2;"><img src="http://thumb7.shutterstock.com/display_pic_with_logo ...

Looping through an array and appending distinct elements to a fresh array

I am currently facing an issue and seeking feedback on how to resolve it. Below is the JSON data: questions: [ { question: 'lala', answer: 'papa', categories: ['Handla'] }, { question: ...

What is the best way to solve the problem of Chrome auto-complete overlapping with labels in Vuetify?

When attempting to make a login form using outlined text fields in Vutify, there is an issue with Chrome autocomplete overlapping the labels. <v-text-field v-model="email" label="e-mail" name="email" outlined prep ...

Vue.js will trigger the updated() method only when a particular array undergoes changes

Working on a chat feature and looking for a way to automatically scroll to the end of the conversation when new messages are added. The current solution involving the updated() function works well, but there's a complication with a vue-timepicker com ...

Methods to Exclude api_key from URL in AngularJS

To make a GET request to a REST API, I require an apikey. The request will be formed like this - $http.get() The response from the API will be in JSON format. However, for security reasons, I don't want the api key to be visible in the URL. Is ther ...

Tips for personalizing the export grid menu in angular-ui-grid?

My grid includes an external "Show Details" option that adds extra columns to the grid when clicked. https://i.sstatic.net/Fu2Qp.png The problem arises with the options for "Export all data" and "Export visible data," which can be confusing in this scena ...

Determining the length of an array of objects within a Firebase array using AngularFire

I have a Firebase structure which looks like this: Chatrooms { -efsCsTB95 { Messages { -bdre3G5 { Title: ... } -wer23bd { Title: ... } } } } This is the view I am working with: <div cla ...

How can you determine the dimensions of an image in HTML using Python?

Is there a way to extract image size information from source code using Python? tree = etree.HTML(source_page_text) image_list = tree.xpath('//img[@src]') The 'img' tags with 'src' attributes can be found using xpath as show ...