Backbone Collection + Instagram API - backbone.js

Hello i have just dived into backbone.
What i am trying to do is make a collection of low_resolution photos from the instagram api feed.
I have model for user that stores all the instagram info like access_token and,
App.Models.Ig_photo({});
And a collection ,
App.Collections.Ig_photos({function() {
model: App.Models.Ig_photo,
url: "https://api.instagram.com/v1/users/self/feed?access_token=",
sync:function (method, model, options) {
options.timeout = 10000; // required, or the application won't pick up on 404 responses
options.dataType = "jsonp";
return Backbone.sync(method, model, options);
},
parse: function( response ) {
return response.data
}
}});
Now i have some issues here, that my collection doesn't get populated when i do fetch and secondly what i wanted was the accesstoken is saved in my another model called user so how do i access it here?
Also it would be great if someone suggests the approach im taking is correct or not. ?

You could add the API key to the collection model:
App.Collections.Ig_photos.access_token = OtherModel.get("access_token");
And use a function for the collection URL:
url: function() {
return "https://api.instagram.com/v1/users/self/feed?access_token=" + this.access_token
},

Related

How to send multiple parameters in AngularJS $http.post to Web API controller action method

How to send multiple parameters in an angularjs $http.post to web api controller action method.
Below is my code.
AngularJS code
var complexObj = { prop1: "value", prop2: "value" };
var id = 100;
var data = { id: id, complexObj: complexObj };
$http({
method: 'POST',
url: 'http://localhost/api/WebApiController/MethodName',
data: data
}).success(function (data, status) {
//do something...
});
$http.post('http://localhost/api/WebApiController/MethodName', data)
.success(function (data, status) {
//do something...
});
Web API controller
[RoutePrefix("api/WebApiController")]
public class WebApiController: ApiController
{
[Route("MethodName")]
public ReturnValue WebApiAction(string id,ComplexObj complexObj)
{
// process request and return data...
}
}
I am getting below response message in fiddler.
{ "message": "No HTTP resource was found that matches the request
URI 'http://localhost/api/WebApiController/MethodName'.",
"messageDetail": "No action was found on the controller
'WebApiController' that matches the request." }
When I send the complexObj alone, its hitting the web api,but all properties are null or set to default values.
What am I doing wrong? How can I send two or more parameters(both complex objects and string/int) in $http.post? Any help is much appreciated.
Web API doesn't support multiple post parameters in this way.
Your best bet is to roll up Id into ComplexObj and post it as a single parameter.
complexObj.id = id;
var data = complexObj;
Update your signature to take just a single object.
[Route("MethodName")]
public ReturnValue WebApiAction(ComplexObj complexObj)
{
// process request and return data...
}
If you absolutely want to be able to post data like this, consider Rick Strahl's post on creating a custom parameter binder.

Sending Array of Objects to Web API from AngualrJS

During this process, I grab an array of "vehicles" from the Web API. I modify and do whatever to each vehicle. Then I want to send the list back, without going through and looping...
I've tried a lot of the ways that i've looked up.
I've got this in the WEB API for a breakpoint to see if I can even get the array there, but I havent been able to yet.
public IHttpActionResult UpdateVehicles(Vehicle[] vehiclesArry)
{
return Ok();
}
I'm confused if I need to do a $post, or if I could just "get" it to the correct method like I've been doing. The problem is I can't get the array to the WEB API method.
I've got my $resource setup like this.
return $resource(appSettings.serverPath + "/api/Violators/:id",null,
{
'update': { method: 'PUT' },
'delete': { method: 'DELETE' },
'post': { method: 'POST' }
});
I've tried using $post, but it says the object doesn't support it. I'm not sure what other ways I can try. I've tried using "dynamic" in the web API, that doesn't seem to work either.
You're missing the params object for $resource, so it doesn't know the id.
return $resource(appSettings.serverPath + "/api/Violators/:id", { id: '#id' });
You don't need to explicitly setup methods for get, post, delete. That's already done for you. If your API uses PUT for update, set that up like this:
return $resource(appSettings.serverPath + "/api/Violators/:id", { id: '#id' }, {
update: { method: 'PUT' }
});
Also, the property on your resource must be vehiclesArry exactly or web API won't know how to map it. I also want to echo #sowen. You will need to setup a view model that your endpoint receives.
My assumption is that you are having some script errors in your page or you are not using the $http methods properly.
One problem people usually run into is using the correct url to the web api endpoints in your angular controller. If you don't get it right, you might be getting 404 errors. Look for those in your browser console(network tab)
The below code should work fine without any issues
$http.get("../api/Values/")
.then(function (res) {
var vehicles = res.data;
console.log('data received', JSON.stringify(vehicles));
//Let's update the Name of each vehicle.
$.each(vehicles, function (indx, item) {
item.Name = item.Name + " Updated";
});
console.log('data modified', JSON.stringify(vehicles));
//Let's make a call to web api with modified data
$http.post("../api/Values/UpdateVehicles", vehicles)
.then(function (res2) {
console.log('response', JSON.stringify(res2.data));
});
});
Assuming you have angular js properly loaded in your page and the above code is part of your angular controller for the current page and you have the Web api controller with 2 action methods like below example.
public class ValuesController : ApiController
{
[HttpPost]
[Route("api/Values/UpdateVehicles")]
public IHttpActionResult UpdateVehicles(Vehicle[] vehiclesArry)
{
// just returning whatever came in for TESTING PURPOSE
return Ok(vehiclesArry);
}
public IEnumerable<Vehicle> Get()
{
return new List<Vehicle>
{
new Vehicle {Id = 1, Name = "Car"},
new Vehicle {Id = 2, Name = "Van"}
};
}
}
Also,FYI : I am using Attribute routing in my api controller for the UpdateVehicle endpoint.
Create a model object like
public class UpdateReq
{
public IEnumerable<Vehicle> Vehicles { get; set; }
}
From your angular, just pass a json with an array
{
[v1, v2, v3]
}

angular object post to laravel db

I have a json formatted post that arrives in the laravel api controller :
public function update($id) {
$post=Request::all();
return $post;
}
the post logs out to the console:
{id: 1, title: "Quiz1", description: "This is a quiz", level_id: 1, questions: Array[2]}
I would like to use the $post data in the laravel api controller to extract the data from the json object array and update my database.
The angular post is:
$scope.updateQuiz = function(quiz) {
$scope.loading = true;
$http.put('/admin/api/quiz/' + quiz.id, {
quiz
}).success(function(data, status, headers, config) {
$scope = data;
console.log($scope.quiz);
$scope.loading = false;
});
};
The code works in that it grabs the angular data and posts it to Laravel function and then posts back to the console in the angular app.
It is just the extraction of individual data that I cannot do.
This seems to work for individual posts but is rather cumbersome:
Angular:
$http.put('/admin/api/quiz/' + quiz.id, {
title:quiz.title
}).success......
Laravel Api:
$quiz->title = Request::input('title');
Wondering how I can avoid listing out all post objects.Must be something obvious I'm missing!?
Thanks.
Is this what you want ?
public function update($id) {
$post = Post::find($id);
if( !is_null($post ) ){
$post->title= $request->input('title');
$post->description= $request->input('description');
//And so on for all fields...
$post->save();
}
}
Note : it's not present in my example above, but you should validate the values received with the laravel validation. See http://laravel.com/docs/5.0/validation#form-request-validation
If your question was about how you redirect the http request to the controller, you should read the routing chapter of the doc : http://laravel.com/docs/5.0/routing
ex :
$app->group(['namespace' => 'App\Http\Controllers'], function($group){
$group->put('/admin/api/quiz/', 'YourController#update');
});

Overrriding collection fetch() method in Backbone.js is causing a double request to the server

I'm doing an application with Backbone.js and Require.js. I have an "Opportunities" Backbone collection and I needed to modify the fetch method because the data from the server comes inside a "results" object.
I did the trick by doing something I found in this question, at this point all looks good.
The problem is that I noticed that the fetch method is asking the server for the data TWO TIMES and not ONE as expected.
I am testing and now I found that if I remove this code: return Backbone.Collection.prototype.fetch.call(this, options); Backbone asks the url for the data only one time, obviously this code is causing the problem but I don't know the reason.
This is my Backbone collection
define([
'backbone',
'models/Opportunity'
], function(Backbone, Opportunity){
var Opportunities = Backbone.Collection.extend({
url: "/api/v1/opps/",
model: Opportunity,
// Need to have custom fetch because json data is coming inside a
// "results" array inside the JSON.
fetch : function(options) {
// store reference for this collection
var collection = this;
$.ajax({
type : 'GET',
url : this.url,
dataType : 'json',
success : function(data) {
// set collection main data
collection.reset(data.results);
}
});
// For some reason this is causing a double request
// to the server
return Backbone.Collection.prototype.fetch.call(this, options);
}
});
return Opportunities;
});
Someone knows the reason because this error is happening?
It's fetching it twice because you're using jQuery to fetch it directly, the calling the models own fetch method which will call an AJAX request as well.
If you want to return data.results back to your collection (and subsequently models), you can use the parse method, like:
var Opportunities = Backbone.Collection.extend({
url: "/api/v1/opps/",
model: Opportunity,
parse: function(data){
return data.results;
}
});

How to structure backbone.js so it returns template + data and ( login-based reroute in mind )

I am building a small app that uses backbone.js on the client side, node.js/socket.io on the server side, and the connection goes trough websockets only.
Now how would I make my setup if I want to get the template and the data at once.
I do a fetch() in the router, which gets the data and the template. With this I construct my view -> collection -> model.
I do a fetch() in the view itself. (Maybe in the initialize)
===
I want to extend this problem with the following.
Let's say a user browses to http://mysite.com/products and the user is not logged in yet, he is not allowed to view the page. He has to be rerouted to /login.
The problem is I can only verify this on the server, so the server has to send back the correct data whether the user is logged in or not, and backbone.js has to deal with this.
Summarized:
I make a fetch to the server which will send back data + template html.
Backbone.js has to render the template with the data,
or reroute (Backbone.history.navigate('login', {trigger: true})) when the server sends back a flag.
You could use parse method in your Backbone collection for example :
Collections.Products = Backbone.Collection.extend({
url : '/products',
parse : function (response) {
//
// you should return JSON from your server and the object must be smth like
// { template : "<p>template for products</p>", data : productsInJSON }
//
if ( response.template && response.data ) {
this.trigger('template', response.template);
return response.data;
} else {
return response;
}
}
});
Views.Page = Backbone.View.extend({
initialize : function () {
_.bind(this, 'render');
var self = this;
this.collection = new Collections.Products();
this.collection.on('template', function(template) {
self.render(template);
});
},
render: function(template) {
$("div#page").html(template);
}
});
$(function() {
window.app = {};
window.app.view = new Views.Page();
// here you are sending {template:true} to '/products' in your server
window.app.view.collection.fetch( { data : { template : true } } );
});
If you are using socket.io, you should create a new Backbone.sync method for your requests.
It is a little bit out of the Backbone philosophy and the integrated GET, PUT, POST, DELETE methods, so there will be a lot of coding.
You could send a template for unlogged in users with no data for the collection.

Resources