What could be causing the AngularJS directive for width not to function properly when switching between Bootstrap tabs?

Having implemented two Bootstrap tabs on a single page, with each tab displaying a list of items, I wanted to ensure that each list item appeared as a square. To achieve this, I created an AngularJS directive which sets the height of each list item equal to its dynamic width under Bootstrap control:

app.directive('squareDiv', function () {
    return {
        restrict: "A",
        link: function (scope, element,attr) {
            scope.getWidth = function () {
                return element.width();
            };
            scope.$watch(scope.getWidth, function (width) {
                element.css({ 
                    height: width + 'px'
                });
            }, true);
        }
    };
});

Upon initial page load, the list items in the first tab appear as squares, indicating that the directive is functioning correctly. However, upon switching to another tab, the list items there revert back to the default height of 100 px. Even after returning to the first tab, the list items no longer display as squares.

What could be causing this issue?

UPDATE 1:

To better illustrate the problem, here is a plunker demonstrating the issue: http://plnkr.co/edit/Pc7keuRXR9R3U6AhZmFE?p=preview

UPDATE 2:

Replacing Bootstrap with UI-Bootstrap in a new plunker still results in the same problem persisting: http://plnkr.co/edit/rLE1wUAHKzJP6FVnGF6b?p=preview

UPDATE 3:

A workaround involved implementing a watch for tab switches rather than width changes, although ideally, understanding why the width watch fails after a tab switch remains a priority: http://plnkr.co/edit/Y4Goe0cexq979JsIcBxl?p=preview

The root cause behind the width watch malfunction following a tab switch is still something I'd like to comprehend.

Answer №1

It appears that your directive's watcher is lagging behind the current state of events. When you click on the very first tab, nothing seems to be happening (no console logs). However, if you pay close attention, you will notice that the elements in your active tab are resizing to match the heights of the elements in the hidden tabs. This indicates that the hidden tab's heights are indeed correct. I recommend using the angular version of Bootstrap over the generic one, as this will ensure better control over all events through Angular.

Check out the Angular version of Bootstrap here

edit: For a deeper understanding of digest cycle triggering and callbacks outside of Angular, you may find this resource helpful: CodeCraftPro - Angular Fundamentals

edit2: You might also find this guide useful for correctly using BootstrapJS and AngularJS together: Scotch.io - Using BootstrapJS and AngularJS Together

Answer №2

It has been observed that the bootstrap tabs switching digest process occurs before the width of your divs change. Rather than monitoring the div widths, it is suggested to track tab changes instead. Upon tab change, a slight delay of 1 ms is introduced to ensure synchronization with the next digest cycle. Subsequently, the width is retrieved and the box height is updated accordingly.

The reason behind this behavior remains unclear, but the following solution has proven to be effective.

For reference, here is a plunker example

Javascript

var app = angular.module("app",['ngAnimate', 'ui.bootstrap']);
app.controller('mainController',['$scope',function($scope){
    $scope.tabs = [
        {'title': 'Tab 1'},
        {'title': 'Tab 2'}
    ];
}]);

app.directive('squareDiv', function ($timeout) {
    return {
        restrict: "A",
        link: function (scope, element, attr) {

            scope.active = function() {
                return scope.tabs.filter(function(tab){
                    return tab.active;
                })[0];
            };

            scope.$watch(scope.active, function (tabActive) {
                $timeout(function() {
                    element.css({ 
                        height: element.width()
                    });
                }, 1);

            });

        }
    }
});

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

Avoid flickering of images by properly handling the object URL when setting the image source in an asynchronous pipe

Implementing a JWT authorized endpoint for images has made it impossible to directly link to image urls in HTML. To work around this issue, we have created an async pipe that loads the image with proper authorization (handled by an HTTP interceptor, not s ...

What is the best way to continuously loop a CSS animation that has multiple keyframe definitions?

Exploring the Challenge In my coding journey, I encountered an interesting dilemma involving two css keyframe animations operating on a single element: .fade-bg { animation-name: fade-bg-1, fade-bg-2; animation-delay: 0, 6s; animation-iteration-cou ...

Obtain elders in jQuery

Here is the HTML code that I am working with: <div class="outter"> .... <div class="container" rel="identification" > <h4> <a href="#" href="www.test.com"> </h4> </div> .... </div> Additionally, I have a ...

Unable to access method from vanilla JavaScript in Vue 3 Custom Element

I've been working with a custom element called <ts-app> that I created using vue 3. The emitted event is functioning correctly, but I'm having trouble figuring out how to call a method from vanilla JavaScript. customElements.whenDef ...

Ways to organize JSON information in JavaScript

The JSON data I have is structured like this. {"count": 3, "records": [ {"common":{"review_date": "2016-02-07 07:00:00","severityid": {"value": "2", "description": "Medium"}}}, {"common":{"review_date": "2016-02-07 08:00:00","severityid": {"value": "2" ...

AngularJS AJAX request failing due to CORS issue

1. I'm having trouble with a CORS error in my AngularJS code for cross domain requests. Despite trying various solutions, I can't seem to pinpoint the mistake. Can someone please help troubleshoot this issue? The specific error message I'm e ...

Contrast the values extracted from an array of objects with a string in React Native/Javascript

I am attempting to implement an If statement to compare a property from an object in an array with a String. I have set up a for-loop, but for some reason, the conditional statement does not seem to be triggering. Below is the code snippet I am using to sa ...

How to completely hide the StatusBar in React Native

Is there a way to completely hide the StatusBar, including the big white rectangle at the top, rather than just hiding the text? <StatusBar hidden/> If this code snippet only hides the text and not the entire StatusBar, how can I achieve that? Thank ...

saving the name of a JavaScript file in the database

I am facing an issue where the JavaScript file name is stored in the database. On the client-side page, I have a jQuery ajax script that retrieves JSON data containing the names of the JavaScript files. Currently, I am using a workaround like the followin ...

Steps for incorporating a scrollbar into the context menu of CKEditor

I am working on adding items to a context menu. However, when too many items are added, they overflow onto the ckeditor area. To solve this issue, I want to implement a scroll bar for the context menu. editor.addMenuItem(suggestionBoxItem, ...

Retrieve MySQL data and insert it into a new table row using jQuery

I am relatively new to using jquery and AJAX and I am unsure if AJAX would be beneficial in this particular scenario. I came across a similar question that seems to be related to what I am looking for. Add new row to table using jQuery on enter key button ...

Eliminating an undesired gap that exists between two ul li elements

Seeking assistance urgently. Any tips on eliminating the annoying small space that separates my 2 UL LI lists? I have a hunch it might be related to the <dd> tag, but pinpointing the exact issue is proving tricky. Check out this visual representati ...

Struggling to perfectly align text in the middle of a div container that also has

Seeking help with aligning text vertically within a div that also contains an image. Previous attempts with CSS properties like vertical-align: center; and line-height:90px have proven ineffective. Removing the image allows for the successful use of line- ...

implement a directive to handle input focus switch within an Angular ng-repeat list

I am faced with the challenge of managing multiple input boxes that utilize filter search binding. Whenever I delete a character, the display results update automatically. However, navigating to each input box and manually deleting text is cumbersome. To ...

Personalizing CSS for showcasing bot icon next to bot reply container

I'm currently working on modifying the layout of this HTML page. I want to include a bot icon next to each bot response, and I also need to decrease the space between consecutive messages. https://i.sstatic.net/lBiMD.png Any suggestions on how I can ...

Utilizing Yii to Partially Render and Send JSON Response via AJAX

My current issue is regarding the return of data. When attempting to send the rendered partial view data from my controller to AJAX, the code provided below will be utilized. JQuery AJAX: $.ajax({ url: "<?php echo $this->createUrl('aj ...

What is the process of nesting an array of objects within an existing object, and how can additional objects be added to the array if it already exists?

I have a JSON file named questions.json containing an array of objects structured like this: { "id": "2", "ques": "here is my second code ?", "quesBrief": "I can't seem to find it too.", "hashes": "#javascript , #goodlord", "author": "slowde ...

Fade in upcoming content over prevailing content utilizing jQuery

Looking to implement a fade-in effect for new posts retrieved from my database. The existing posts are initially loaded in a div when the page loads, and I would like the new posts to smoothly appear above the old ones. Recently began exploring jQuery and ...

Utilizing Chosen JS along with the clone(true,true) method for re-rendering upon appending

I am currently utilizing the Chosen JS jQuery plugin and attempting to make it re-render every time a cloned element, with all its event listeners copied over, is added to the document. Below is my code snippet: var container = jQuery(self.options.parent ...

ASP.NET submit button not triggering after JavaScript function execution

I created a textbox with onpress and onblur events. The Javascript function will format the text to (xx-xxxxx). <input type="text" id="txtnum" onblur="javascript:return formatText(this)" onkeypress="javascript:return formatText(this)"> ...