如何为谷歌位置创建angularjs自定义指令

时间:2015-07-02 03:57:35

标签: angularjs angularjs-directive

我尝试使用<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&libraries=places&language=en-US"></script>创建一个指令来查找谷歌位置,如下所示:

angular.module('MyApp').directive('locationPicker', function () {

    return {
        restrict: 'AE',
        replace: true,
        require: 'ngModel',
        template: '<input id="{{id}}" type="text" class="{{class}}" placeholder="{{placeholder}}" />',
        scope: {
            id: '@',
            class: '@',
            placeholder: '@',
        },
        link: function ($scope, elm, attrs, controller) {

            var autocomplete = new google.maps.places.Autocomplete(elm[0], {types: ['geocode']});

            var componentForm = {
                locality: 'long_name',
                administrative_area_level_1: 'short_name',
                country: 'long_name'
            };

            google.maps.event.addListener(autocomplete, 'place_changed', function () {

                var place = autocomplete.getPlace();
                var lat = place.geometry.location.lat();
                var lng = place.geometry.location.lng();

                var name = "";

                for (var i = 0; i < place.address_components.length; i++) {
                    var addressType = place.address_components[i].types[0];
                    if (componentForm[addressType]) {
                        if (name !== "") {
                            name += ", ";
                        }

                        var val = place.address_components[i][componentForm[addressType]];
                        name += val;
                    }
                }

                elm[0].value = name;
                $scope.$apply(function () {
                    controller.$setViewValue({name: name, lat: lat, lng: lng});
                });
            });
        }
    };
});

我的意见:

<input id="location" location-picker ng-model="location" class="form-control" placeholder="Project location" ng-required="true" />

在我的控制器中:

$scope.location = {
   name:null,
   lat:null,
   lng:null
};

一切看起来都很好但是当我的组件首次渲染时,输入的值是[Object object]而不是占位符(Project Location)。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

问题

您正在将ngModel绑定到位置对象,该位置对象在强制转换为字符串时呈现为[object Object]

解决方案

由于您抓住指令中的NgModelController,您可以使用其$formatters管道转换模型值(位置对象namelatlng属性)到视图值和$render函数中,以指定在ngModel生命周期之外更改值时如何呈现值。

这是一个工作的掠夺者:http://plnkr.co/edit/5HPFelbDFUrzeccGfgYx?p=preview。关键的代码是

// triggered by $setViewValue
controller.$formatters.push(function (value) {
    return value ? value.name : value;
});

// triggered by clear() from controller
controller.$render = function () {
    input.value = controller.$modelValue.name;
};

我还对您的代码进行了以下修改:

  1. 使用location-picker作为元素指令。 input不是一个很好的元素选择,因为它已经绑定到ngModel
  2. 已移除replace: true。它是指令中不推荐使用的配置选项,可能会导致一些奇怪的行为,因为它试图混合指令元素的属性和模板元素的属性。
  3. 已移除elm[0].value = name;。当您致电ngModel时,这会由$setViewValue的生命周期处理。