Подтвердить что ты не робот

Почему эта ширина, смотрящая директиву AngularJS, не работает при переключении вкладок Bootstrap?

У меня есть две вкладки Bootstrap на странице, и на каждой вкладке отображается список. Я хочу, чтобы каждый элемент списка был квадратом и написал эту директиву AngularJS, чтобы установить высоту каждого элемента списка равным его динамической ширине, контролируемой Bootstrap:

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

Когда я загружаю эту страницу, элементы списка первой вкладки отображаются как квадраты, что означает, что директива работает. Но когда я нажимаю на другую вкладку, элементы списка имеют высоту по умолчанию 100 px. Когда я вернусь к первой вкладке, даже элементы списка теперь имеют высоту по умолчанию.

Что здесь происходит?

ОБНОВЛЕНИЕ 1:

Вот ссылка на плункер, который иллюстрирует эту проблему: http://plnkr.co/edit/Pc7keuRXR9R3U6AhZmFE?p=preview

ОБНОВЛЕНИЕ 2:

Plunker с Bootstrap заменен на UI-Bootstrap, который по-прежнему имеет ту же проблему: http://plnkr.co/edit/rLE1wUAHKzJP6FVnGF6b?p=preview

ОБНОВЛЕНИЕ 3:

Plunker с часами для переключателя табуляции вместо изменения ширины (обходной путь для исходной проблемы с часовым механизмом не работает правильно, необходимо будет использовать отдельную директиву для адаптации к изменениям ширины из-за изменения размера окна): http://plnkr.co/edit/Y4Goe0cexq979JsIcBxl?p=preview

Я все равно хотел бы понять, почему часы ширины перестают корректно работать после переключения табуляции.

4b9b3361

Ответ 1

Ваш наблюдатель-директив - это один из циклов дайджест, который происходит из-за того, что происходит. Если вы посмотрите достаточно внимательно, вы увидите, что самый первый щелчок на вкладке не делает многого (ничего не записывается в консоль). Вы видите, что ваши активные элементы вкладки изменяются на высоту элементов скрытых вкладок. Таким образом, скрытые высоты вкладок верны. Я настоятельно рекомендую использовать версию bootstrap angular вместо общей. Таким образом, все (события) будут находиться под управлением angular.

https://angular-ui.github.io/bootstrap/

edit:, это может быть полезно для понимания запуска и обратного вызова цикла дайджеста вне angular: http://school.codecraftpro.com/courses/angularjs-1x-fundamentals/lectures/392422

edit2: также полезно https://scotch.io/tutorials/how-to-correctly-use-bootstrapjs-and-angularjs-together

Ответ 2

Мы знаем, что дайджест перестановки вкладок бутстрапа опережает ширину ваших div. Поэтому вместо того, чтобы наблюдать за изменением ширины ваших div, пусть вместо этого наблюдайте, когда изменяется вкладка. Когда вкладка изменится, подождите 1 мс, чтобы убедиться, что мы находимся в следующем цикле дайджеста. Затем получите ширину и обновите высоту окна.

Я понятия не имею, почему это так, но вот решение, которое будет работать.

Вот пример plunker

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

            });

        }
    }
});