AngularJS ng-src async functions

I'm creating a simple web application to show Formula 1 drivers. The list of drivers is retrieved via a public API. I have a link to their wikipedia page, so I'm trying to obtain the main image to use as a profile pic.

I extract the wikipedia page title from the url and then perform a further JSON call to wikipedia to get the url of the image.

Getting the list of drivers and binding to the page works fine, but my function call never seems to populate the ng-src attribute, even though the JSON call is triggered. Console logging shows the img url is returned, but it never populates the img.

The following is my controller.js

angular.module('formulaOneApp.controllers', []).controller('DriverViewController', function($scope, $stateParams, Driver) {
  $scope.data = Driver.driver.get({ id: $stateParams.id }, function(){
    $scope.driver = $scope.data.Drivers[0];
  });

  $scope.getProfilePic = function(driverName) {
    if (driverName == undefined) return;
    console.log(driverName)

    $.getJSON("http://en.wikipedia.org/w/api.php?callback=?",
    {
        action: "query",
        titles: driverName,
        prop: "pageimages",
        format: "json",
        pithumbsize: "200"
    }, function(data) {
        $.each(data.query.pages, function(i,item){
            console.log(item.thumbnail.source)
            return item.thumbnail.source;
        });
    });
  }
});

This is my html: -

<h3>Details for {{driver.givenName}} {{driver.familyName}}</h3>
<img ng-src="{{ getProfilePic(driver.wikiName) }}" />

I do suspect this may not be the correct approach, so can anyone point me in the right direction?

The implementation of getProfilePic(...) retrieves the data, but you're not actually saving your source paths anywhere. To approach this correctly, you wouldn't put the data retrieval call into the ng-src attribute (because it will execute repeatedly on every $digest). Instead, you'd do the retrieval call right from your controller

$scope.data = Driver.driver.get({ id: $stateParams.id }, function(){
    $scope.driver = $scope.data.Drivers[0];
    $scope.getProfilePic($scope.driver.wikiName).then(function (url) {
        $scope.driver.imageUrl = url;
    });
});

$scope.getProfilePic = function(driverName) {
    return $http.get("http://en.wikipedia.org/w/api.php?callback=?", { ... }, function (data) {
        // ... get the image URL from the data and return it
    });
});

and save the URL you get to a scope variable. Then just link to that variable from your template:

<img ng-src="{{driver.imageUrl}}">

(I've only used $http.get instead of $.getJSON, because I don't use jQuery. Feel free to adjust that bit, but keep in mind that the jQuery AJAX methods don't return AngularJS promises.)


And a free bonus hint: Whether using jQuery promises or AngularJS promises, learn how they are chained. In AngularJS, a clean version of your controller code would look like this:

getDriver($stateParams.id)
    .then(function (driver) {
        $scope.driver = driver;
    })
    .then(function () {
        return getDriverImageUrl($scope.driver.wikiName);
    })
    .then(function (url) {
        $scope.data.imageUrl = url;
    });

function getDriver (id) {
    return $http({
        // ...
    });
}
function getDriverImageUrl (driverName) {
    return $http({
        // ...
    });
}