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

Когда мы узнаем фактическую ширину элемента в Angular?

Я пытаюсь создать директиву, которая будет центрировать div.

До сих пор у меня этот код:

app.directive("setcenter", function () {
    return {
        scope:{
            setcenter: '='
        },
        link: function (scope, element, attrs) {

            scope.$watch('setcenter', function (newValue) {
                if (newValue == true) {
                    var width = element.width();
                    element.css('position', 'absolute');
                    element.css('top', '80px');
                    element.css('left', '50%');
                    element.css('z-index', '200');
                    element.css('margin-left', '-' + width / 2 + 'px');
                }
            });
        }
    }
});

Проблема заключается в ширине элемента. Весь смысл этой директивы в том, что div, который использует эту директиву, не имеет ширины. Я хочу, чтобы эта директива определяла ширину и центр div.

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

Итак, что я могу сделать, чтобы дождаться фактической ширины в div?

4b9b3361

Ответ 1

Во-первых, я использовал эту логику только тогда, когда я определил контроллер для директивы, а не для функции link. Поэтому определение его в функции ссылок может привести к другому поведению, но я предлагаю вам сначала попробовать его, и если вы не можете заставить его работать, переключитесь на использование контроллера.

Насколько я могу судить, единственным изменением, которое вам нужно было бы сделать для этой работы, было бы изменение $scope на вызовы области и $element на элемент, так как объекты, вложенные зависимостями, становятся стандартными параметрами функции ссылки.

  $scope.getElementDimensions = function () {
    return { 'h': $element.height(), 'w': $element.width() };
  };

  $scope.$watch($scope.getElementDimensions, function (newValue, oldValue) {
    //<<perform your logic here using newValue.w and set your variables on the scope>>
  }, true);

  $element.bind('resize', function () {
    $scope.$apply();
  });

Идея этого использования пришла ко мне после прочтения очень похожего типа использования о просмотре окна $, а не текущего элемента, здесь можно найти оригинальную работу.

Angular.js: установить высоту элемента при загрузке страницы

Ответ 2

Ответ Джеймса привел меня к:

app.directive('measureInto', function () {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                scope.$watch(function() {
                    return element[0].clientWidth;
                }, function(value){
                    scope[attrs.measureInto] = element[0].clientWidth + 10;
                });
            }
        };
    });

Итак, во время выполнения я добавляю это и назначаю в любую переменную области видимости я хочу ширину элемента, который я ищу

Ответ 3

У меня была аналогичная проблема, и я обнаружил, что размеры были достоверно правильными, когда все ng-ifs (или что-то еще, использующее ngAnimate) на странице были разрешены - возможно, что-то подобное происходит здесь. Если это так, это сделало бы трюк без добавления новых слушателей:

$scope.tryGetElementDimensions = function () {
    if (!angular.element("your-element") || ((angular.element("your-element")[0].classList).contains("ng-animate")
       $timeout(function() {
           $scope.tryGetElementDimensions()
       })
    }
    else {
        $scope.getElementDimensions()
    } 

$scope.getElementDimensions = function (){
    //whatever you actually wanted to do
}

link: function (scope, element, attrs) {
    $scope.tryGetElementDimensions()
}

Angular добавляет классы ng-animate и ng-enter, ng-leave во время анимации, и вы можете быть уверены, что они закончили, когда все эти классы были удалены. $timeout без второго аргумента просто ждет следующего дайджеста.

Ответ 4

Не могу комментировать, поэтому этот ответ. Нашел аналогичное решение, подобное тому, которое предлагает strom2357. $timeout работает очень хорошо, чтобы сообщить вам, когда дом готов, и это очень просто. Я использую это решение, чтобы получить ширину элемента ui-view. Нашел в скрипке.

var app = angular.module('app', []);

app.controller('MyController', function($timeout, $scope){

  $timeout(function(){
    //This is where you would get width or height of an element
    alert('DOM ready');
  });

  alert('DOM not ready');

});