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

时间:2015-08-18 15:43:32

标签: javascript angularjs

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

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

我正在使用ng-if因为我没有加载谷歌地图/街景,直到它所在的标签打开。问题是它第一次显示一切正常但第二次ng-if为真(当你点击另一个标签然后返回标签时)它似乎将long和lat设置为undefined。

我知道以下内容:

A)如果我将ng-hide更改为ng-show它就可以了。每次离开nad返回标签时,谷歌地图都不会被销毁和创建,所以这是有道理的。这与ng有关 - 如果在我认为它是假的时候会破坏某些东西。

B)在父控制器中实际上改变了lat和long值,因为我在那里放了一个$ watch和一个console.log()来测试它。基本上当ng-if设置为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>

1 个答案:

答案 0 :(得分:2)

违规行是:

$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",并根据调用$scope的{​​{1}}对其进行评估。

您使用$eval作为参数调用它,这意味着评估的表达式类似于$scope.latitude - 显然不是在范围上定义的内容 - 因此您得到35.344542。< / p>

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

quickView

但更重要的是,您甚至根本不需要此$scope.$parent.$eval($attrs.latitude) ,因为$eval已经通过双向绑定自动获取了评估值。以下也可以起作用:


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