Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript angularJS:等待ng if完成,以确保DOM已准备就绪_Javascript_Angularjs_Dom - Fatal编程技术网

Javascript angularJS:等待ng if完成,以确保DOM已准备就绪

Javascript angularJS:等待ng if完成,以确保DOM已准备就绪,javascript,angularjs,dom,Javascript,Angularjs,Dom,我使用ng if来显示和隐藏元素。当元素出现时,我想调用一个服务,它在新元素中滚动到某个子元素(通过Id)。问题是,如果我在将元素设置为visible之后立即尝试调用服务函数,DOM似乎还没有准备好 var myApp = angular.module('myApp',[]); myApp.factory("ScrollService", function () { return { scroll: function (id) { console

我使用ng if来显示和隐藏元素。当元素出现时,我想调用一个服务,它在新元素中滚动到某个子元素(通过Id)。问题是,如果我在将元素设置为visible之后立即尝试调用服务函数,DOM似乎还没有准备好

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

myApp.factory("ScrollService", function () {
    return {
        scroll: function (id) {
            console.log(document.getElementById(id));
        }
    };
});

function MyCtrl($scope, ScrollService) {
    $scope.visible = false;

    $scope.toggleVisibility = function () {
        $scope.visible = !$scope.visible;
        if ($scope.visible) {
            ScrollService.scroll("myId"); //output: null
        }
    };
}
document.getElementById()
将始终导致
null

这里还有一把小提琴,说明了问题所在:

那么,在被ng if操纵后,有没有办法在DOM准备就绪后立即触发函数

编辑

使用MinkoGechev的小提琴,我能够在更现实的环境中重现我的错误,并使用指令而不是服务:

问题似乎发生了,因为我在
ng if
-容器内使用
ng repeat

<div ng-controller="MyCtrl">
    <div ng-if="visible"> 
        <div id="myId" data-scroll="itemId">
            <div id="xy"></div>
            <div ng-repeat="item in items" id="{{ item.number }}">{{ item.number }}</div>
        </div>
    </div>
    <button ng-click="toggleVisibility()">toggle</button>
</div>

如果我使用1到10之间的一个数字(ng repeat创建的元素ID),它将失败。如果我使用的是“xy”(位于ng repeat元素旁边的一个元素的Id),则会成功。

以下是如何通过指令实现所需效果:

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

myApp.directive("scroll", function () {
    return {
        scope: {
            scroll: '='
        },
        link: function (scope) {
            scope.$watch('scroll', function (v) {
                //The value is true, so the element is visible
                console.log(v, document.getElementById('myId'));
            });
        }
    };
});

function MyCtrl($scope) {
    $scope.visible = false;

    $scope.toggleVisibility = function () {
        $scope.visible = !$scope.visible;
    };
}
这里是(打开控制台查看日志)


注意:AngularJS强制分离关注点,从而产生可读性和可维护性更高的代码。使用“角度方式”时应遵循的规则之一是将所有DOM操作仅放在指令中。

找到解决问题的方法了吗

既然您提到问题似乎与ng repeat有关,您是否尝试过“scope.$last?”

我决不是一个有经验的web开发人员,但我也遇到过类似的问题,工具提示不会显示在ng repeat“生成”的项目上,并使用使用“scope.$last”应用工具提示的指令使其工作

例如:

AppName.directive('directiveName', function () {
    return function (scope, element, attrs) {
        if (scope.$last) {
            <-- Your code here -->
        }
    };
});
AppName.directive('directiveName',function(){
返回函数(范围、元素、属性){
如果(范围$last){
}
};
});

也许有经验的人可以提供更多的信息。

请不要在控制器中实现DOM,使用指令instead@MaximShoustin我没有将其实现到控制器中,而是实现到服务中。我还尝试使用一个指令,得到了相同的结果。@basilikum在指令的
link()
函数中,您可以确定链接到此指令的元素的DOM已准备就绪。在这里,您必须将元素滚动到他的孩子那里。@Blackhole也是一个很好的建议,但它似乎还没有完全准备好,因为ng repeat中的元素还没有出现(请参见更新的问题)。谢谢您的回答,我看到您的小提琴工作正常。不幸的是,当我在我的应用程序中实现这一点时,它就不再工作了。也许还有别的事情。我稍后会再回答。我刚刚编辑了我的问题。看来,这个错误与使用ng repeat有关。你知道我做错了什么吗?
var myApp = angular.module('myApp',[]);

myApp.directive("scroll", function () {
    return {
        scope: {
            scroll: '='
        },
        link: function (scope) {
            scope.$watch('scroll', function (v) {
                //The value is true, so the element is visible
                console.log(v, document.getElementById('myId'));
            });
        }
    };
});

function MyCtrl($scope) {
    $scope.visible = false;

    $scope.toggleVisibility = function () {
        $scope.visible = !$scope.visible;
    };
}
AppName.directive('directiveName', function () {
    return function (scope, element, attrs) {
        if (scope.$last) {
            <-- Your code here -->
        }
    };
});