0

So I am building an Ionic app just to get familiar with it and it's my first time using Angular and i'm not quite in the Angular way of thinking yet.

I have two services, one that returns a location, and another that returns weather for that location. I have my data being organized in the service and send to the controller where I use the services function in the controller to set $scope variables for each of the data points to use in the view. I am wanting to integrate a 'pull to refresh' feature within the controller and for now I just have copied my code that was originally in the controller and wrapped it in a ion.Refresher directive. What is the best way of keeping this code DRY.

Thanks!

services.js

angular.module('weather.services', [])

.service('getLocation', function($http){
  this.getData = function(lat, long) {
    var promise = $http({
      method: 'GET',
      url: 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' + lat + ',' + long
    }).success(function(data) {
      data.location = data.results[3].address_components[0].long_name;
      return data.location;
  });
  return promise;
 }
})

.service('getWeather', function($http){
  this.getData = function(lat, long) {
    var promise = $http({
        method: 'jsonp',
        url:  'https://api.forecast.io/forecast/api-key/' + lat + ',' + long + '?callback=JSON_CALLBACK'
    }).success(function(data) {
      data.currentTemperature = parseInt(data.currently.temperature);
      data.summary = data.currently.summary;
      data.icon = data.currently.icon;

      var timestamp = moment.unix(data.currently.time);
      var formattedDate = moment(timestamp, "YYYY-MM-DD HH:mm:ss")
      data.todaysDate = formattedDate.format('dddd Do MMMM');

      var daily_data = data.daily.data;
      var days = []
      angular.forEach(daily_data, function(value, key) {
        this.push(value);
      }, days);
      data.dailyWeather = days;

      // hourly weather for side scroll
      var hourly_data = data.hourly.data;
      var hours = []
      angular.forEach(hourly_data, function(value, key) {
       this.push(value);
      }, hours);
      data.hourlyWeather = hours;

      return data;
    });
    return promise;
   }
 })

controller.js

angular.module('weather.controllers', [])

.controller('HomeCtrl', function($scope, $http, getLocation, getWeather, $cordovaGeolocation) {

  $cordovaGeolocation
    .getCurrentPosition()
    .then(function (data) {
      $scope.latitude = data.coords.latitude;
      $scope.longitude = data.coords.longitude;

      // Gets location and city you are in
      getLocation.getData($scope.latitude, $scope.longitude).then(function(data){
        $scope.location = data.data.location;
      })

      // Gets the weather data for the city you are in
      getWeather.getData($scope.latitude, $scope.longitude).then(function(weather){
        $scope.weather = weather.data;
        $scope.today = weather.data.todaysDate;
        $scope.weather.currentTemp = weather.data.currentTemperature;
        $scope.weather.summary = weather.data.summary;
        $scope.weather.icon = weather.data.icon;
        $scope.weather.daily = weather.data.dailyWeather;
        $scope.weather.hourly = weather.data.hourlyWeather;
      })
    }, function(err) {
      console.debug(err);
    });

    // see the repeated code
    $scope.doRefresh = function() {
      console.log('currently refreshing data')
      $cordovaGeolocation
        .getCurrentPosition()
        .then(function (data) {
          $scope.latitude = data.coords.latitude;
          $scope.longitude = data.coords.longitude;

          // Gets location and city you are in
          getLocation.getData($scope.latitude, $scope.longitude).then(function(data){
            $scope.location = data.data.location;
          })

          // Gets the weather data for the city you are in
          getWeather.getData($scope.latitude, $scope.longitude).then(function(weather){
            $scope.weather = weather.data;
            $scope.today = weather.data.todaysDate;
            $scope.weather.currentTemp = weather.data.currentTemperature;
            $scope.weather.summary = weather.data.summary;
            $scope.weather.icon = weather.data.icon;
            $scope.weather.daily = weather.data.dailyWeather;
            $scope.weather.hourly = weather.data.hourlyWeather;
          })

          $scope.$broadcast('scroll.refreshComplete');
        }, function(err) {
          console.debug(err);
        });
    }
});
3
  • stop using success() it is deprecated (see $http docs). In your case chaining then() is more appropriate anyway and most of the processing code in your controller is better moved to the service. Then return one object to assign to $scope.weather Commented Sep 14, 2016 at 14:11
  • cool thanks man - switching over to .then Commented Sep 14, 2016 at 14:36
  • in fact if you kept the property names you use in your scope the same as what gets returned from the weather api it would cut down need to assign each property also which is a lot of extra work Commented Sep 14, 2016 at 14:39

1 Answer 1

1

You can do like this to keep your code DRY, it's the same as others:

.controller('HomeCtrl', function($scope, $http, getLocation, getWeather, $cordovaGeolocation) {

  $scope.loadData = function(isRefreshing) {
     ...// your code to load location and weather data here.
     //// 
     if (isRefreshing) {
        // broadcast your event
     }
  }

  $scope.loadData(); // load data for the first time
  $scope.doRefresh = function() {
     $scope.loadData(true); // load data on refreshing
  }
Sign up to request clarification or add additional context in comments.

5 Comments

all except for the event broadcast...which could be triggered based on argument in loadData()
what do you mean?
You just need to put your code that do the same thing in a function then call it instead of rewrite everything.
I see, put a boolean variable isRefreshing, if it's true then broadcast the event.
right but in one case an event is broadcast but not in the other

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.