6

I'm trying to import json object into variable. I use the services according to tutorial.

I receive unexpected token error, because i shouldn't use $scope.news = JsonSource.feed(); - but I really don't know what should I use. I googled and searched 3 hours I find only $http. or $json. answers, but I feel, that it could be done easier - clearer.

(The perfect solution would be $scope.news = JsonSource.feed().entries ;D

The services file:

var AAAServices = angular.module('AAAServices', [
    'ngResource'
]);

AAAServices.factory('JsonSource', ['$resource',
  function($resource) {
    return $resource('https://www.facebook.com/feeds/page.php', {}, {
      feed: {method:'JSONP', {format: 'json', id:'459908', callback : JSON_CALLBACK}, isArray:false}
      });
  }]);

The controllers file:

var AAAControllers = angular.module('AAAControllers', [])
AAAControllers.controller('newsCtrl', ['$scope', 'JsonSource', 
  function newsCtrl($scope, JsonSource) {
     $scope.news = JsonSource.feed();
}]);

the json file (almost ;D)

{
   "title": "Tytuł",
   "link": "https:\/\/www.facebook.com\/",
   "entries": [
      {
         "title": " news 1",
         "id": "1"
      },
      {
         "title": " news 2",
         "id": "2"
     }
   ]
}

Edited:

i change $resource('file.json into https://www.facebook.com/feeds/page.php - so you can check if it is json or jsonp...

Tomasz Brzezina
  • 1,452
  • 5
  • 21
  • 44

2 Answers2

8

I did not notice that it takes to be a JSONP, so I did it with default $resource method.

Below is an example that does what you want. Please remember to:

  • include a file angular-resource.min.js
  • inject ngResource to services module
  • inject motoAdsServices to app module
  • inject Brand to controller
  • the rest will do Angular :)

index.html

<!DOCTYPE html>
<html ng-app="motoAdsApp">

  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-resource.min.js"></script>
    <script type="text/javascript" src="controllers.js"></script>
    <script type="text/javascript" src="services.js"></script>
  </head>

  <body>
    <div ng-controller="AdvertsController">
      <label>Brand</label>
      <select name="brand" ng-model="brand" ng-options="b.name for b in brands">
        <option value=""></option>
      </select>
    </div>
  </body>

</html>

services.js

var motoAdsServices = angular.module('motoAdsServices', ['ngResource']);

motoAdsServices.factory('Brand', ['$resource', function($resource) {
    return $resource('./brands.json', {}, {});
  }]);

controllers.js

var motoAdsApp = angular.module('motoAdsApp', ['motoAdsServices']);

motoAdsApp.controller('AdvertsController', ['$scope', 'Brand', 
  function($scope, Brand) {

    $scope.brands = Brand.query();
}]);

brands.json

[
  {"name": "Audi", "models": [{"name": "A1"}, {"name": "A3"}, {"name": "A4"}]},
  {"name": "BMW", "models": [{"name": "Series 3"}, {"name": "Series 5"}, {"name": "Series 7"}]},
  {"name": "Citroen", "models": [{"name": "C1"}, {"name": "C2"}, {"name": "C3"}]},
  {"name": "Dacia", "models": [{"name": "Duster"}, {"name": "Logan"}, {"name": "Sandero"}]}
]

Plunker example

UPDATE (because should be JSONP)

To use JSONP you should only change services.js

var motoAdsServices = angular.module('motoAdsServices', ['ngResource']);

motoAdsServices.factory('Brand', ['$resource', function($resource) {
    return $resource('./brands.json', {}, {
         jsonpquery: { method: 'JSONP', params: {callback: 'JSON_CALLBACK'}, isArray: true }
    });
  }]);

and controllers.js

var motoAdsApp = angular.module('motoAdsApp', ['motoAdsServices']);

motoAdsApp.controller('AdvertsController', ['$scope', 'Brand', 
  function($scope, Brand) {

    $scope.brands = Brand.queryjsonp();
}]);

And it shoould be work. But server should return valid jsonp.

There is the same problem: jsonp request with angular $resource And he found that there was a problem with server.

UPDATE 2 (because the problem is probably with CORS in node.js server)

server.js (node.js)

var express = require('express');
var path = require('path');
var http = require('http');
var brands = require('./routes/brands');
var countries = require('./routes/countries');
var adverts = require('./routes/adverts');

var app = express();

// ALLOW CORS!!!
var allowCrossDomain = function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
};

app.configure(function() {
  app.set('port', process.env.PORT || 3000);
  app.use(express.logger('dev'));  /* 'default', 'short', 'tiny', 'dev' */
  app.use(express.bodyParser()),
          app.use(allowCrossDomain);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.get('/api/brands', brands.findAll);
app.get('/api/countries', countries.findAll);
app.get('/api/adverts', adverts.findAll);

http.createServer(app).listen(app.get('port'), function() {
  console.log("Express server listening on port " + app.get('port'));
});

routes/brands.js

exports.findAll = function(req, res) {
  var fs = require('fs');
  var file = './server/data/brands.json';

  fs.readFile(file, 'utf8', function(err, data) {
    if (err) {
      throw err;
    }
    res.send(JSON.parse(data));
  });
};

UPDATE 3 (because CORS should be added to web-server.js (node.js) without express)

You have something like: https://github.com/angular/angular-seed/blob/master/scripts/web-server.js

So you have to add ALLOW CORS (look below I added 2 lines) to response headers:

StaticServlet.prototype.sendFile_ = function(req, res, path) {
  var self = this;
  var file = fs.createReadStream(path);
  res.writeHead(200, {
    'Content-Type': StaticServlet.
      MimeMap[path.split('.').pop()] || 'text/plain',
    // ALLOW CORS - line 1 !!!
    'Access-Control-Allow-Origin' : '*',
    // ALLOW CORS - line 2 !!!
    'Access-Control-Allow-Headers': 'X-Requested-With'
  });
  if (req.method === 'HEAD') {
    res.end();
  } else {
    file.on('data', res.write.bind(res));
    file.on('close', function() {
      res.end();
    });
    file.on('error', function(error) {
      self.sendError_(req, res, error);
    });
  }
};

Maybe you have other function with jsonp, so add to res.writeHead(200, CORS headers too.

UPDATE 4 - ANGULARJS CALL FACEBOOK BY JSONP

THIS SOLUTION SHOULD BE WORK !!!

services.js

var myServices = angular.module('myServices', ['ngResource']);

myServices.factory('FacebookFeed', ['$resource',
  function($resource) {
    return $resource('https://graph.facebook.com/cocacola?callback=JSON_CALLBACK', {}, {
      jsonp_query: {
        method: 'JSONP'
      }
    });
  }
]);

controllers.js

var myApp = angular.module('myApp', ['myServices']);

myApp.controller('MyController', ['$scope', 'FacebookFeed', 
  function($scope, FacebookFeed) {
    $scope.feeds = FacebookFeed.jsonp_query();
    console.log()
}]);

index.html

<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-resource.min.js"></script>
    <script type="text/javascript" src="controllers.js"></script>
    <script type="text/javascript" src="services.js"></script>
  </head>

  <body>
    <div ng-controller="MyController">
      <label>Facebook feeds</label></label>
      <pre>{{feeds}}</pre>
    </div>
  </body>

</html>

Plunker example

Community
  • 1
  • 1
lukpaw
  • 1,603
  • 2
  • 26
  • 31
  • unfortunately the json is on outside server, so the Access-Control-Allow-Origin problem appears... I found that the best solution is to use jsonp – Tomasz Brzezina Nov 17 '13 at 09:06
  • Look at my update maybe it help you. When Access-Control-Allow-Origin problem apears. Your server should allow CORS request. – lukpaw Nov 17 '13 at 09:09
  • this is exactly what I set - i found no difference. But how to check if server returns valid jsonp? – Tomasz Brzezina Nov 17 '13 at 09:10
  • 1
    What about CORS your server allow it? For example in node.js server you should do `res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With");` to allow CORS. So maybe problem is not with Angular but with server. – lukpaw Nov 17 '13 at 09:11
  • where should i put it? I definitely newbie with node.js – Tomasz Brzezina Nov 17 '13 at 09:16
  • Look at my update 2. It is complete my server.js and brands.js in node.js. – lukpaw Nov 17 '13 at 09:19
  • I don't have anything comparable to your server. I use angular-seed web-script.js – Tomasz Brzezina Nov 17 '13 at 20:27
  • 1
    I have just looked at your updated resource url in your answer. I think that server `https://www.facebook.com/feeds/page.php` should response CORS headers yet. Why you use angular-seed web-script.js if you call `https://www.facebook.com/feeds/page.php`? – lukpaw Nov 17 '13 at 22:41
  • Look at update 4. There is working solution (also plunker example) - angulajs call facebook by JSONP. It should be work for you. – lukpaw Nov 17 '13 at 23:02
  • I was sure, that client should set Access-Control-Allow-Origin' : '*', not server... – Tomasz Brzezina Nov 17 '13 at 23:24
  • graph.facebook.com/cocacola isn't what i want - page.php gives me wall content - which i can see in my browser. But when server (localhost) tries to get this content - facebook refuses... Now I know where's the problem... Damnit...It was so close to have easy wall content... Two days lost – Tomasz Brzezina Nov 17 '13 at 23:27
  • Put your answer (cors) here: http://stackoverflow.com/questions/20036008/angular-seed-web-script-js-and-cors - you should be gratified for your big job with accepted answer – Tomasz Brzezina Nov 17 '13 at 23:52
  • Yes, I know that you want to call `https://www.facebook.com/feeds/page.php` but I think that it should be the same principle like in call `graph.facebook.com/cocacola`. It's nice that you solved the problem. – lukpaw Nov 18 '13 at 07:16
-3

This is the answer for those, who thinks (as me) that if something works in browser it should work in server scripts.

  1. facebook gives very nice json for the wall content:

https://www.facebook.com/feeds/page.php?format=json&id=xxxx

  1. But you can't get it from nodejs - because of cross domain policy-restriction

More about is here: Loading facebook wall feed JSON issues

So, now i have to search for jsonp stream for facebook wall... Sigh....

Community
  • 1
  • 1
Tomasz Brzezina
  • 1,452
  • 5
  • 21
  • 44