自定义指令在ng-if中第二次绑定不正确

Custom directive not binding correctly in ng-if second time around

本文关键字:第二次 绑定 不正确 ng-if 指令 自定义      更新时间:2023-09-26

我有一个自定义指令,它使用双向绑定到我的控制器(使用'=')。

<my-streetview 
    latitude="quickView.streetView.latitude" 
    longitude="quickView.streetView.longitude" 
    ng-if="quickView.activeTab === 'street'"
></my-streetview>

我使用ng-if是因为我不希望谷歌地图/街景被加载,直到它所在的标签被打开。麻烦的是,第一次它显示一切工作,但第二次ng-if是真的(当你点击一个不同的选项卡,然后回到选项卡),它似乎设置了长和晚未定义。

我知道以下内容:

A)如果我改变ng-hide为ng-show,它只是工作。每次你离开并返回标签页时,谷歌地图不会被破坏和创建,所以这是有道理的。我想,这和ng-if破坏错误的东西有关。

B)后期和长值实际上在父控制器中被更改,因为我在那里放置了一个$watch和一个console.log()来测试它。基本上,当ng-if在第一次创建街景fine时被设置为true时,第二次和随后的时间它要么无法从父控制器读取值,要么实际上将它们设置为未定义。

C)在第一次显示ng-if和随后的次数之间没有其他不同。我想不出还有什么别的代码可以发挥作用。

如有任何意见,我将不胜感激。

这是我的街景指令的完整代码。

angular.module('my.directives')
.constant('myStreetviewDefaults', {
    latitude: 51.816102,
    longitude: -0.811619
})

.directive('myStreetview', function ($timeout, myStreetviewDefaults) {
    return {
        restrict: 'EA',
        scope: {
            latitude: '=',
            longitude: '='
        },

        link: function ($scope, $element, $attrs) {
            $scope.latitude = angular.isDefined($scope.latitude) ? $scope.$eval($scope.latitude) : myStreetviewDefaults.latitude;
            $scope.longitude = angular.isDefined($scope.longitude) ? $scope.$eval($scope.longitude) : myStreetviewDefaults.longitude;

            // Create the panorama
            var mapEl = $('<my-streetview-map></my-streetview-map>');
            mapEl.addClass('my-streetview-map-container');

            $element.append(mapEl);
            var panorama = new google.maps.StreetViewPanorama(mapEl[0], {
                position: {
                    lat: $scope.latitude,
                    lng: $scope.longitude
                },
                pov: {
                    heading: 34,
                    pitch: 10
                }
            });

            // Watch latitude and longitude to reset the center
            $scope.$watchGroup(['latitude','longitude'], function (newValues, oldValues, $scope) {
                panorama.setPosition({
                    lat: $scope.latitude,
                    lng: $scope.longitude
                });
            });

            // Hack to get street view drawing properly on second load
            // https://github.com/allenhwkim/angularjs-google-maps/issues/59
            $timeout(function(){
                google.maps.event.trigger(panorama,'resize'); 
            }, 100);
        }

    };

});

这是街景所在的Angular UI模态的控制器代码。

angular.module('app')
.controller('QuickViewCtrl', function ($rootScope, $scope, $log, $http, appConfig, $u, $modalInstance, modalSettings) {
    'use strict';
    var master = $scope.master;
    var quickView = this;

    $log.info('Quick View Opened', modalSettings);

    this.close = function(){
        $modalInstance.close();
    }
    ///////////////////////////////////////////////////////////////
    //  Initialize Page
    ///////////////////////////////////////////////////////////////
    var init = function () {
        // Set the initial tab
        quickView.activeTab = modalSettings.initialPanel;

        // Set up the street view
        quickView.streetView = {
            latitude: modalSettings.property.latitude,
            longitude: modalSettings.property.longitude
        };

        $scope.$watch('quickView.streetView', function(newValues, oldValues){
            console.log("Test watching from controller", newValues);
        }, true);

    };
    init();
});

这是模态窗口的模板....

<div class="quickView modal-inner modal--has-header modal--has-footer">
    <!-- Header -->
    <div class="modal-header">
        <!-- Header removed for brevity -->
    </div>
    <div class="modal-main">
        <!-- Tabs -->
        <my-tabset
            my-tabset-active-tab="quickView.activeTab" 
        >
            <div my-tabset-tabs my-tabset-tabs--equal4>
                <a href="#" my-tabset-tab my-tabset-tab-name="overview" is-active="true">
                    <div my-tabset-tab-text>Overview</div>
                </a>
                <a href="#" my-tabset-tab my-tabset-tab-name="gallery">
                    <div my-tabset-tab-text>Gallery</div>
                </a>
                <a href="#" my-tabset-tab my-tabset-tab-name="map">
                    <div my-tabset-tab-text>Map</div>
                </a>
                <a href="#" my-tabset-tab my-tabset-tab-name="street">
                    <div my-tabset-tab-text>Street View</div>
                </a>
            </div>
            <div my-tabset-panels>
                <!-- Overview Panel -->
                <div my-tabset-panel my-tabset-tab-name="overview" is-active="true">
                    <div ng-if="quickView.activeTab === 'overview'">
                        <!-- Overview removed for brevity -->
                    </div>
                </div>
                <!-- Gallery Panel -->
                <div my-tabset-panel my-tabset-tab-name="gallery">
                    <div ng-if="quickView.activeTab === 'gallery'">
                        <!-- Gallery removed for brevity -->
                    </div>
                </div>
                <!-- Map Panel -->
                <div my-tabset-panel my-tabset-tab-name="map">
                    <ui-gmap-google-map 
                        center='quickView.map.center' 
                        zoom='quickView.map.zoom' 
                        options="quickView.map.options" 
                        control="quickView.mapControl" 
                        ng-if="quickView.activeTab === 'map'"
                    >
                        <ui-gmap-marker
                            idKey="'quickViewMapMarker'" 
                            coords='quickView.map.markerPosition'
                        >
                        </ui-gmap-marker>
                    </ui-gmap-google-map>
                </div>
                <!-- Street View Panel -->
                <div my-tabset-panel my-tabset-tab-name="street">
                    <my-streetview 
                        latitude="quickView.streetView.latitude" 
                        longitude="quickView.streetView.longitude" 
                        ng-if="quickView.activeTab === 'street'"
                    ></my-streetview>
                </div>
            </div>
        </my-tabset>
    </div>

    <!-- Footer -->
    <div class="modal-footer">
        Footer
    </div>
</div>

违规行如下:

$scope.latitude = angular.isDefined($scope.latitude) ? $scope.$eval($scope.latitude) : myStreetviewDefaults.latitude;
$scope.longitude = angular.isDefined($scope.longitude) ? $scope.$eval($scope.longitude) : myStreetviewDefaults.longitude;

不清楚你为什么使用$scope.$eval($scope.latitude),但它可能源于对$scope.$eval的误解。

$scope.$eval取一个表达式,例如:"quickView.streetView.latitude",并根据调用$eval$scope求值。

你用$scope.latitude作为参数来调用它,这意味着求值的表达式类似于35.344542——显然不是作用域上定义的东西——所以你得到了undefined

也许你打算使用$attrs.latitude -这将给你"quickView.streetView.latitude"表达式,但你需要在父范围上调用它,因为你的指令使用一个不知道quickView(等…)是什么的隔离范围:

$scope.$parent.$eval($attrs.latitude)

但更重要的是,你甚至根本不需要这个$eval,因为$scope.latitude已经通过双向绑定自动获取了求值。下面的代码也同样有效:

<>之前美元的范围。latitude = angular.isDefined($scope.latitude)? scope.latitude美元: myStreetviewDefaults.latitude;