Когда мы узнаем фактическую ширину элемента в 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?
Ответы
Ответ 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');
});