3

Right now I've created a JS API with JQuery, but I'm wondering if it could be done with AngularJs.

For example, Imagine a small API like the following:

var $myapi= $myapi|| {};
;(function($, window, document, undefined){
    _call_myapi_jsonp: function(params,controller,action,eventName){
    if (!params) params = {};

    var url = this.urls.base+"/"+controller+"/"+action+"?callback=?";
    if (params.callback)
        url = this.urls.base+"/"+controller+"/"+action+"?callback="+params.callback;
    url = url + "&_"+new Date();
    delete params.callback;
    $.ajax({
        url: url,
        data: params,
        crossDomain:true,
        dataType:'jsonp',
        cache:false,
        ajaxOptions: {cache: false},
        jsonp: params.callback?false:true,
        success:function(data,status){
            if (eventName && eventName!=""){
                $($myapi).trigger(eventName,data);
            }
        }
    });
},
    level: {
    list: function(params){
        params = params || {};
        params.max = params.max!=undefined?parseInt(params.max):$myapi.defaults.levels.max;
        params.page = params.page!=undefined?parseInt(params.page):$myapi.defaults.levels.page;
        params.showActives = params.showActives!=undefined?params.showActives:$myapi.defaults.levels.showActives;
            $myapi._call_myapi_jsonp(params,"level","listJSONP","myapi.level.list");
        },
        info: function(params){
            $myapi._call_myapi_jsonp(params,"level","showJSONP","myapi.level.info");
        }
    }
}

I've been searching through AngularJs Documentation and also searching in Google, but I have not found a way in which the code in Jquery could be made in AngularJS. I thought maybe using $routeProvider it could be done, but I have'nt found any example nor documentation on how to use $routeProvider to make jsonp calls without showing a template or redirecting to some place.

GFoley83
  • 3,439
  • 2
  • 33
  • 46
Eylen
  • 2,617
  • 4
  • 27
  • 42

1 Answers1

2

It sounds like what you need is a service, akin to what's being done here:

Recommended way of getting data from the server

http://jsfiddle.net/wpPhY/

but with the inclusion of $resource:

http://docs.angularjs.org/api/ngResource.$resource

Here's a basic example of a JSONP service to query Twitter (taken from http://egghead.io):

JSFiddle Demo: http://jsfiddle.net/gavinfoley/DJ6da/

angular.module('Twitter', ['ngResource']);

angular.module('Twitter')
.controller('TwitterCtrl', ['$scope', '$resource', function ($scope, $resource) {
    $scope.twitter = $resource('http://search.twitter.com/:action',
        {action:'search.json', q:'angularjs', callback:'JSON_CALLBACK'},
        {get:{method:'JSONP'}});

    $scope.doSearch = function () {
        $scope.twitterResult = $scope.twitter.get({q:$scope.searchTerm});
    };
}]);

Also, it would be worth taking a look at using Breeze with Angular. I haven't used it myself but you can create some really cool CRUD apps with it:

http://www.breezejs.com/samples/todo-angular

If however you're looking to gain access to functions or properties defined inside of a particular Angular controller (or scope) from jQuery, take a look at the Plnkr and code below.

To be honest, I really wouldn't go down this road if at all possible. It would be better to remove jQuery from your solution altogether and just stick with Angular. Meaning write your Angular API or service and consume it using Angular controllers/directives etc.

In other words, if you're going to use Angular in your application then go "all Angular". Don't try to mix and match with jQuery. It will only slow you down and make your code harder to maintain.

Full Plnkr Demo: http://plnkr.co/edit/X5SfKD?p=preview

HTML

<!DOCTYPE html>
<html data-ng-app="myApp">
  <head>
    <link rel="stylesheet" href="style.css">
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
    <script src="myApp.js"></script>
    <script src="script.js"></script>
  </head>
  <body>    
    <div id="parent" data-ng-controller="ParentCtrl">     
        <span id="someSpan">This is {{name}}.</span>    
        <div id="child" data-ng-controller="ChildCtrl">This is {{name}}.</div>    

        Get latest tweet for: <input type="text" data-ng-model="twitterUser" />

        <button data-ng-click="getLatestAngularTwitterPost()">Get Tweet</button><br/><br/>

        Latest {{searchTerm}} Twitter post:
        <div>        
            <img id="twitterProfileImage" data-ng-src="{{profileImage}}" />
            <span data-ng-bind-html-unsafe="tweet" id="tweet"></span>
        </div>    
    </div>    
  </body>
</html>

Angular app - myApp.js

angular.module('myApp', []);

angular.module('myApp')
.controller('ParentCtrl', function ($scope,  $http) {
    $scope.name = "parent";    
    $scope.testFunc = function () {
        return "Test is working."
    };
    $scope.twitterUser = "AngularJS";
    $scope.tweet;
    $scope.profileImage;
    $scope.searchTerm;

    // Returns latest post on Twitter from AngularJS
    $scope.getLatestAngularTwitterPost = function (callbackFunc) {        
        $scope.searchTerm = $scope.twitterUser;        
        var url = "http://api.twitter.com/1/users/show.json";

        $http.jsonp(url, {
          params: {
            callback: 'JSON_CALLBACK',
            screen_name: $scope.twitterUser
          }
        })
        .success(function(data){
            if(callbackFunc){
                console.log("Passing twitter results to callback: " + callbackFunc.name);
                return callbackFunc(data);
            }

            $scope.tweet = data.status.text;
            $scope.profileImage = data.profile_image_url;          
        })
        .error(function() {
            $scope.tweet = "<strong>Error: could not make JSONP request to Twitter.</strong>"; 
        });
    };
});

angular.module('myApp')
.controller('ChildCtrl', function ($scope) {
    $scope.name = "child";
});

jQuery - script.js

// Ex. of how to call methods and update properties 
// in Angular controllers, from jQuery
$(function () {
    // Get Angular controller "ParentCtrl".
    // Could also use $('#someSpan').scope(); to get "ParentCntl" scope
    var $scopeParentCtrl = $('#parent').scope();
    // Get Angular controller "ChildCtrl".
    var $scopeChildCtrl = $('#child').scope();

    // Update the "name" property in Angular controller "ParentCtrl"
    $scopeParentCtrl.$apply(function(){
      $scopeParentCtrl.name = "Joe";
      console.log("Parent name changed to " + $scopeParentCtrl.name);
    });

    // Update the "name" property in Angular controller "ChildCtrl"
    $scopeChildCtrl.$apply(function(){
      $scopeChildCtrl.name = "Gavin";
      console.log("Child name changed to "+ $scopeChildCtrl.name);
    });

    // Call the "testFunc" function in Angular conroller "ParentCtrl"
    console.log($scopeParentCtrl.testFunc());

     // Call the JSONP function in Angular controller "ParentCtrl"
    $scopeParentCtrl.getLatestAngularTwitterPost(jsonpCallback);      
});

function jsonpCallback(data) {
    var $scopeParentCtrl = $('#parent').scope();
    $scopeParentCtrl.tweet = data.status.text;
    $scopeParentCtrl.profileImage = data.profile_image_url;
}
Community
  • 1
  • 1
GFoley83
  • 3,439
  • 2
  • 33
  • 46
  • but in this way, could you call from, for example, chrome console to those functions? – Eylen Apr 29 '13 at 12:40
  • Thanks for the answer, it achieves better what I was thinking. I know I should avoid mixing AngularJS an jQuery, but I must provide and interface for third's integration, so I can't tell them 'use Angular'. – Eylen Apr 30 '13 at 09:22
  • @Eylen: Glad to help. If you still want to write your API in jQuery, you could call it from an Angular controller/directive with the use of `$scope.apply();`. See this question and answer: http://stackoverflow.com/questions/14716822/using-jquerys-ajax-within-an-angularjs-controller. If you setup a Plnkr or JSFiddle with the code, i'd be happy to take a look and help you out if I can. – GFoley83 Apr 30 '13 at 10:58
  • Thanks for the tip but I think I still don't understand something... How could you make a call to an angular method in a controller from a js script that's not angular? If I have time I'll try to fill a jsfiddle or plunker – Eylen May 09 '13 at 14:57
  • @Eylen: That's exactly what the jQuery code above is showing you! E.g. In my jQuery doc ready code I'm calling `$scopeParentCtrl.getLatestAngularTwitterPost("jsonpCallback");` & `$scopeParentCtrl.testFunc();` both of which are functions inside the Angular controller `ParentCtrl`. I've updated the plunker and code above to also show how you can make changes to properties inside your Angular controllers, from jQuery using `$scope.apply()`. – GFoley83 May 09 '13 at 22:30
  • That's true! Thanks for your help. I think I was a bit sleepy when I wrote that, or blind :P – Eylen May 13 '13 at 14:15
  • 'http://search.twitter.com/:action' the twitter api version here is old & will not work. Returns a '410 Gone'. Has to be updated to V1.1 endpoints. – bootload Sep 11 '13 at 05:32
  • 1
    @bootload Yeah needs OAuth now so not gonna bother updating. The code still answers OP question which is the main thing. – GFoley83 Sep 11 '13 at 06:11