0

So I'm trying to get use to angular and having some troubles trying to call a directive (google maps https://github.com/davidepedone/angular-google-places-map) and performing reverse geocoding. I think this would be a more general directives questions though.

I am trying to call a function within the directive to update the google maps place information as well as map. The way I'm thinking in my head is that I would need to pass a variable through the controller, scope that variable to the directive and then the directive will run the function?

UPDATED:

 <div class="row">
 <places-map selectedid="selectid(place.id)"></places-map>
 </div>
 <button ng-click="selectid(place.id)">{{place.id}}</button> </div> 

With this click I suppose to go to the controller,

$scope.selectid= function (pickplaceid){
   $scope.selectedid(pickplaceid);
}

Then the selectplaceid should be in the scope variables of the directive.

        scope: {
            customCallback: '&?',
            picked: '=?',
            address: '=?',
            fallback: '=?',
            mapType: '@?',
            readonly: '@?',
            responsive: '@?',
            draggable: '@?',
            toggleMapDraggable: '=?',
            placeNotFound: '=?',
            updateMarkerLabel: '=?',
            selectedid:'='
        },

and can call my method as so:

 link: function ($scope, element, attrs, controller) {
 //everything else from angular-google-places

            $scope.selectedid= function (selectedplace)
            {
 ///Whatever I want to do to geocode with the placeid
            }

I think I may just be doing this completely wrong having really no luck with the directive call at all. I'm trying to update my map based on the location that I click and pull out the information of that specific place from the placeId. Any help would be great.

Julius Doan
  • 356
  • 1
  • 4
  • 20
  • You are creating an isolated scope in your directive, so it has no idea of the variables in the controller. You need to pass the variables you need in the html: – cYrixmorten Nov 29 '15 at 09:13
  • Isn't this just saying your scope selectplaceid=place.id? How would it call the function selectplaceid? – Julius Doan Nov 29 '15 at 18:35
  • Actually, after re-reading your question I would think that you could change `$scope.selectplaceid = pickplaceid;` into `$scope.selectplaceid(pickplaceid);` in you controller, to invoke the method inside your directive. You however still need to pass the function to your directive in HTML, as you have created an isolated scope. Have a look at the example passing customerInfo in the documentation: https://docs.angularjs.org/guide/directive – cYrixmorten Nov 29 '15 at 18:44
  • Yes so that was my question, how to call the isolated directive scope function from the html side? I understand when we are setting a $scope to a value shown in the customerInfo example but functions seem a bit different? – Julius Doan Nov 29 '15 at 18:55
  • Oh thats right, it needs to be passed as a function parameter using `&` it seems. I know I have done something similar but not at my work PC atm. Perhaps this is an helpful example: http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters – cYrixmorten Nov 29 '15 at 19:23
  • Thanks I will take a look at this. Yea i modified it to the & scope to take in the function, but wasn't able to get it to work yet. – Julius Doan Nov 29 '15 at 19:25
  • Please update the code in your question instead, easier to read ... also the scope of your directive etc. Alternatively boil your problem down to the simplest case possible: how to call a method on a directive. Makes it a lot easier to help if we can do a simple JSFiddle or something to play around with. – cYrixmorten Dec 03 '15 at 09:52
  • @cYrixmorten Updated. Hope this clears it up. – Julius Doan Dec 03 '15 at 16:48

1 Answers1

0

I have almost same thing working, and I solved it with a Service that receives a placeId (in my code it's called addressId, but it's the placeId Google Maps expects). In my service, I use the placeId to retrieve address details:

  app.service('AddressDetailsService', ['$q', function ($q) {

    this.placeService = new google.maps.places.PlacesService(document.getElementById('map'));

    this.getDetails = function (addressId, address) {
      var deferred = $q.defer();

      var request = {
        placeId: addressId
      };

      this.placeService.getDetails(request, function (place, status) {
        if (status === google.maps.places.PlacesServiceStatus.OK) {
          address.placeId = addressId;
          address.street = getAddressComponent(place, 'route', 'long');
          address.countryCode = getAddressComponent(place, 'country', 'short');
          address.countryName = getAddressComponent(place, 'country', 'long');
          address.cityCode = getAddressComponent(place, 'locality', 'short');
          address.cityName = getAddressComponent(place, 'locality', 'long');
          address.postalCode = getAddressComponent(place, 'postal_code', 'short');
          address.streetNumber = getAddressComponent(place, 'street_number', 'short');
          address.latitude = place.geometry.location.lat();
          address.longitude = place.geometry.location.lng();

          if (address.streetNumber) {
            address.streetNumber = parseInt(address.streetNumber);
          }
          deferred.resolve(address);
        }
      });

      return deferred.promise;
    };

    function getAddressComponent(address, component, type) {
      var country = null;
      angular.forEach(address.address_components, function (addressComponent) {
        if (addressComponent.types[0] === component) {
          country = (type === 'short') ? addressComponent.short_name : addressComponent.long_name;
        }
      });

      return country;
    }
  }]);

Then you inject it and call the service from your directive. This is the one I use, you might need to adapt it, but you see the idea. Instead of a link function, I use a controller for the directive:

  .directive('mdAddressDetails', function mdAddressDetails() {
    var directive = {
      restrict: 'EA',
      scope: {
        address: '='
      },
      bindToController: true,
      templateUrl: 'modules/address/addressDetails.html',
      controller: AddressDetailsController,
      controllerAs: 'dir'
    };

    AddressDetailsController.$inject = ['AddressDetailsService', '$q'];

    function AddressDetailsController(AddressDetailsService, $q) {
      var dir = this;

      dir.selectAddress = selectAddress;

      function selectAddress(address) {
        if ((address) && (address.place_id)) {
          AddressDetailsService.getDetails(address.place_id, dir.address).then(
            function (addressDetails) {
              dir.address = addressDetails;
            }
          );
        }
      }
    }

    return directive;
  });

And then you just call the directive with the wanted parameter:

  <md-address-details address="myAddress"></md-address-details>
Leo Lozes
  • 1,358
  • 1
  • 15
  • 33
  • interesting take on putting the controller rather than linking it. Since I already have a directive I am confused on how your ng-click would invoke the directive? – Julius Doan Nov 29 '15 at 19:29
  • Sorry! Missed that part. I guess it would be something like this: http://stackoverflow.com/questions/15613992/ng-click-attribute-on-angularjs-directive so you actually have the ng-click inside your directive, and handle it there. – Leo Lozes Nov 29 '15 at 21:33
  • So I am a bit confused how is this using the place-map directive? Since my directive is the autocomplete with the Google Maps, and I have an ng-click separate from the directive I'm confused how this works? What I am seeing here is that your directive will invoke the service which will pull the maps data. – Julius Doan Dec 03 '15 at 05:13
  • My directive also uses the autocomplete, but I removed it because I thought you weren't going to use it. What are you trying to achieve? We have an autocomplete with Maps, and when the user selects an address, we retrieve the details. Is that what you are trying to do? – Leo Lozes Dec 03 '15 at 11:14
  • So we have an auto complete. We save the data from the auto complete in our database. Then on the side we have a table of the saved placeid. When clicked on one of the placeid it refers back to the map and updates the location. So geocoding the saved placeid from the autocomplete saved info. Hope that clears it up. – Julius Doan Dec 03 '15 at 14:12