Get values from object using Backbonejs - javascript

i want to get value from this API http://demo82.com/lois/api/get_page/?id=6 using Backbone js. i tried but i don't know how can we get values from object in backbone.
here is my Backbone code
Page = Backbone.Model.extend({
initialize: function() {
this.on('all', function() { console.log(this.get('page')); });
},
url: "http://demo82.com/lois/api/get_page/?id=6",
defaults: {
"id":null,
"title":"",
"content":""
}
});
var page = new Page();
console.log(page.fetch({}));
i am new and try to learn backbonejs please explain what is the better way ? please give me ans using jsfiddle.net.
thanks

Is id always going to be 6? In your code, your model is always getting the 6th thing. If you want a custom url with a get parameter, override url as a function:
url: function() {
id = this.get("id");
return "loispage/api/get_page/?id=" + id
}
Better yet, if you have control over the server side and can do something a little more RESTful with a page entity -- simply set urlRoot
urlRoot: "loispage/api/page/"
and fetch will automatically do an HTTP get from
"http://.../loispage/api/page/<id>

It looks like a context problem (this doesn't refer to the model in on's callback). You can fix this by specifying the context:
this.on('all',
function() { console.log(this.get('pagel')); },
this
);
Edit
There's also a cross-domain issue. You'll need to use a JSONP request for this by overriding sync and parse. (I adapted the following code from this example.)
var Page= Backbone.Model.extend({
// override backbone synch to force a jsonp call
sync: function(method, model, options) {
// Default JSON-request options.
var params = _.extend({
type: 'GET',
dataType: 'jsonp',
url: model.url(),
processData: false
}, options);
// Make the request.
return $.ajax(params);
},
parse: function(response) {
// parse can be invoked for fetch and save, in case of save it can be undefined so check before using
if (response) {
console.log(JSON.stringify(response));
// here you write code to parse the model data returned and return it as a js object
// of attributeName: attributeValue
return { status: response.status }; // just an example
}
},
Here's a JSFiddle demo.

Related

Can Mockjax handle single IDs Api from Json file

I'm using Mockjax for the first time to mock a Restful API which will return a series of data given an id. Right now i have a json file that has several Items, and i would like to have a function inside Mockjax (or where necessary) to return only the queried ID. how can I achieve this?
current code :
$.mockjax({
url: "/Api/Cases/{caseId}",
proxy: "/mocks/cases nuevo.json",
dataType: 'json',
responseTime: [500, 800]
});
$.ajax({
type: 'GET',
url: '/Api/Cases/',
data: {caseId: taskId},
success: function(data){
//use the returned
console.log(data);
}
});
current error:
GET http://localhost:8080/Api/Cases/?caseId=100 404 (Not Found)
Great question... yes, you can do this. But you'll have to write the functionality yourself using the response callback function and then making a "real" Ajax request for the file (instead of using the proxy option). Below I just make another $.ajax() call and since I have no mock handler setup for that endpoint, Mockjax lets it go through.
Note that setting up URL params is a little different than you suggest, here is what the mock setup looks like:
$.mockjax({
url: /\/Api\/Cases\/(\d+)/, // notice the regex here to allow for any ID
urlParams: ['caseID'], // This defines the first matching group as "caseID"
responseTime: [500, 800],
response: function(settings, mockDone) {
// hold onto the mock response object
var respObj = this;
// get the mock data file
$.ajax({
url: 'mocks/test-data.json',
success: function(data) {
respObj.status = 200;
// We can now use "caseID" off of the mock settings.urlParams object
respObj.responseText = data[settings.urlParams.caseID];
mockDone();
},
error: function() {
respObj.status = 500;
respObj.responseText = 'Error retrieving mock data';
mockDone();
}
});
}
});
There is one other problem with your code however, your Ajax call does not add the ID to the URL, it adds it to the query string. If you want to use that API endpoint you'll need to change your source code $.ajax() call as well. Here is the new Ajax call:
$.ajax({
type: 'GET',
url: '/Api/Cases/' + taskId, // this will add the ID to the URL
// data: {caseId: taskId}, // this adds the data to the query string
success: function(data){
//use the returned
console.log(data);
}
});
Note that this presumes the mock data is something like:
{
"13": { "name": "Jordan", "level": 21, "id": 13 },
"27": { "name": "Random Guy", "level": 20, "id": 27 }
}
What I have ended up doing, is: I have left the $.mockjax function untouched, and i have manipulated the data inside the ajax request, using jquery's $.grep function as follows:
$.ajax({
type: 'GET',
url: '/Api/Cases/' + taskId,
success: function(data){
//note you have to parse the data as it is received as string
data = JSON.parse(data);
var result = $.grep(data, function(e){ return e.caseId == taskId; });
//since i'm expecting only one result, i pull out the result on the 0 index position
requestedData = result[0];
}
});
The $.grep() method removes items from an array as necessary so that all remaining items pass a provided test see Jquery API, And since our test is that the caseId attribute of the element equals to the taksId variable sent, it will return all the elements that match the given Id, in this case, only one, this is why I've taken only the result on the 0 index position requestedData = result[0];
**Note: **
A more suited solution would be a mixture between what i've done and #jakerella 's answer, since their method implements the find element method inside the mockjacx function, and my function presumes a usual JSON response:
[{"caseId": 30,"name": "Michael"},{"caseId": 31,"name": "Sara"}]

How to get backbone model to do a POST on fetch?

I'm trying to get backbone to do a POST when I call fetch on a model, but nothing I've tried so far seems to work. I also need to pass multiple parameters in the fetch (not just an ID), and need to use jsonp.
I tried overriding the sync method in the model to look like below so that it will do the POST, but it doesn't seem to work (a GET call is still being made).
sync: function(method, model, options) {
if (method === "read") {
method = "create";
}
return Backbone.sync.call(this, method, model, options);
}
And the fetch looks something like this:
var model = new MyModel();
var deferred = model.fetch({
dataType: "jsonp",
data: {
parm1: "somevalue",
parm2: false,
parm3: {
type1: "abc",
type2: "123"
}
}
});
Any ideas on why this would not be working?
Thanks so much!!
You can pass type as part of the fetch method options argument.
What will happen is that Backbone will sync your request as a read method, which it is, and just before calling jQuery's ajax method it will override the type, as you can see in Backbone's source code.
var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
So your code should look something like that:
var model = new MyModel();
var deferred = model.fetch({
type: "post",
dataType: "jsonp",
data: {
parm1: "somevalue",
parm2: false,
parm3: {
type1: "abc",
type2: "123"
}
}
});
Remember that the options you pass to the fetch method are basically jQuery's ajax options, with the extension of Backbone's options.
You need to set the type to "post" in the options that are passed to Backbone.sync. As mentioned in the sync docs, options is "success and error callbacks, and all other jQuery request options":
sync: function(method, model, options) {
var opts = options;
if (method === "read") {
method = "create";
opts = $.extend({}, opts, {
type: "post"
});
}
return Backbone.sync.call(this, method, model, opts);
}

Backbone.js default path (subdomain)

I am using CORS so all the API happens in api.mywebsite.com but the website is served via website.com.
I am wondering if there's a way I can set the setting of either jQuery or Backbone to always make AJAX requests to my api.mywebsite.com ?
In otherwords, I want to do this in my backbone collections:
url: '/books'
and have it automatically infer api.mywebsite.com/v1/books
For the collection you can specify the full URL:
YourApp.Collections.Books = Backbone.Collection.extend({
model: YourApp.Models.Book,
url: 'http://api.mywebsite.com/v1/books/'
});
And for individual resources you can use a function to generate the url:
YourApp.Models.Book = Backbone.Model.extend({
url: function() {
return 'http://api.mywebsite.com/v1/books/' + this.get('id')
}
});
Backbone has the urlRoot method that sets the root of all requests.
From the Backbone site:
var Book = Backbone.Model.extend({urlRoot : '/books'});
var solaris = new Book({id: "1083-lem-solaris"});
alert(solaris.url());
alerts "/books/1083-lem-solaris"
Of-course you can change that relative path to something else: put a dot in front to send it to the site root, or your specific site root, or give it an absolute path.
Documentation
Of course in jQuery you can build the URL to whatever you like in an AJAX request. Including to an absolute url as long as it's not another domain:
$.ajax({
type: "GET",
url: "http://api.mywebsite.com + "anything_you_want_to_add"
}).done(function(response) {
console.log(response);
receiveResponseMethodSomewhereElse(response);
});
And a quick Backbone example of using the url parameter of the Model or the Collection:
The showing the scripts I used:
<title>Backbone Test</title>
<meta charset="UTF-8">
<script src="jquery.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>
And then I specifically pointed this backbone example at my localhost. You'd want to point it to your domain. I included all of the console logs and available responses for your debugging pleasure. Both options here are building urls from the book id as that's normall what your creating, Reading, Updating or Deleting from the server. I put this script directly within the body of the page and watched the console logs. Note: Backbone is expecting a JSON response.
<script>
var Book = Backbone.Model.extend({urlRoot: 'http://localhost/url_test'});
var BookCollection = Backbone.Collection.extend({
model: Book,
url: 'http://localhost/url_test'
});
var myExcellentBook = new Book({id: "book"});
var MyBooks = new BookCollection();
// getting it directly from the model
solaris.fetch({
success: function(model, response, options) {
console.log("SUCCESS");
console.log(model);
console.log(response);
console.log(options);
},
error: function(model, response, options) {
console.log("ERROR");
console.log(model);
console.log(response);
console.log(options);
},
complete: function(xhr, textStatus) {
console.log(textStatus);
}
});
// or fetch directly from the collection and
// normally you'd loop through the response or
// when creating new models, you can let backbone
// intialize them through the response
MyBooks.fetch({
success: function(model, response, options) {
console.log("SUCCESS");
console.log(model);
console.log(response);
console.log(options);
},
error: function(model, response, options) {
console.log("ERROR");
console.log(model);
console.log(response);
console.log(options);
},
complete: function(xhr, textStatus) {
console.log(textStatus);
}
});
</script>
And the php script at url_test is simply returning a JSON object.
<?php
echo '[{"id": "MyNewBook"}]';

AngularJS 1.2.0 $resource PUT/POST/DELETE do not send whole object

I'm using angularjs 1.2.0 with $resource. I would like to have some PUT/POST instance actions that doesn't send the whole object to the server but only some fields and in some cases totally no data.
Is it possible? I searched everywhere but couldn't find anything
UPDATE:
It also happens with DELETE requests:
Given this code:
group.$deleteChatMessage({messageId: message.id}, function(){
var i = _.indexOf(group.chat, message);
if(i !== -1) group.chat.splice(i, 1);
});
The request is this:
See how the whole model is sent (under "Request Payload").
This is the resource:
var Group = $resource(API_URL + '/api/v1/groups/:gid',
{gid:'#_id', messageId: '#_messageId'},
{
deleteChatMessage: {method: "DELETE", url: API_URL + '/api/v1/groups/:gid/chat/:messageId'},
});
This works for me:
$resource(SERVER_URL + 'profile.json',
{},
{
changePassword :
{
method : 'POST',
url : SERVER_URL + 'profile/changePassword.json',
// Don't sent request body
transformRequest : function(data, headersGetter)
{
return '';
}
}
});
You could customise exaclty what is sent to the server by implementing your own code in the transformRequest function. In my example I was adding a new function to the REST client, but you can also overwrite existing functions. Note that 'transformRequest' is only available in version 1.1+
You can use $http for that specifically. However, I have one case I use for a project that might help. Also my example is returning an array from the server but you can change that.
In my service:
app.factory('mySearch', ['$resource', function($resource) {
return $resource('/api/items/:action', {}, {
search: { method: 'POST', isArray: true,
params: { action: 'search' }
}
});
}
]);
In my Controller:
I can build up custom params to post to server or if its only two fields I need from a table row the user selects.
var one = "field_one";
var two = "field_two";
$scope.search({one: one, two: two});
Then I can post those through an event and pass the custom params
$scope.search = function(customParams) {
mySearch.search({query: customParams}, function(data) {
$scope.items = data;
}, function(response) {
console.log("Error: " + response.status);
})
};
Hopefully this was some help. Let me know if this is close to what your looking for and I can help more.
POST
DELETE

How to do an ajax post, from javascript, to a web-api service

I'm trying to make a logging method, that works on all my javascript calls.
It is not going too well. I get the following error:
No action was found on the controller 'Log' that matches the request.
I have the following code, on my controller:
[System.Web.Mvc.HttpPost]
public void Post(string msg)
{
using (var ctx = new DataClassesDataContext(ConfigurationManager.ConnectionStrings["EasyViewDkConnectionString"].ToString()))
{
ctx.UserInputInsert(msg, HttpContext.Current.Request.UserHostAddress);
}
}
VERY simple. I am a bit unsure if it my routing that is the problem. Basically, I just have the default route:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
To post the data, I'm using this javascript:
function Log(msg) {
$.ajax({
url: "/api/Log/",
data: msg,
type: "POST",
contentType: "application/json;charset=utf-8"
});
}
So obviously, I'm doing something wrong. It is probably my routing, but I can't seem to solve it. I have tried changing the msg argument on the controller, to id, but it's still the same.
I've been googling around for a while now, and I stumbled upon this article:
http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
It turns out, web Api doesn't really like it when you post a primitive value, like a string. To get it to work, you need to add [FromBody]to the parameter and also have a blank value name, when posting.
So, I have changed my code around a bit, and it now looks like this, and works.
Javascript:
function Log(msg) {
$.post("/api/Log", { "": msg });
}
And my controller:
[System.Web.Http.HttpPost]
public HttpResponseMessage Post([FromBody]string value)
{
using (var ctx = new DataClassesDataContext(ConfigurationManager.ConnectionStrings["EasyViewDkConnectionString"].ToString()))
{
ctx.UserInputInsert(value, HttpContext.Current.Request.UserHostAddress);
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
Another possibility that has worked for me in the past...
You may possibly consider changing your mapping to include the controller action
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Then change your url in the ajax method to [controller]/[method]/. You would also need to define your post data argument.
$.ajax({
url: "/api/Log/Post/", //--'Log' being the Controller, 'Post' being the method
data: JSON.stringify({"msg":msg}),
type: "POST",
contentType: "application/json;charset=utf-8"
});
Hope that helps. Keep us posted!

Categories

Resources