I can't see what the problem with this is.
I'm trying to fetch data on a different server, the url within the collection is correct but returns a 404 error. When trying to fetch the data the error function is triggered and no data is returned. The php script that returns the data works and gives me the output as expected. Can anyone see what's wrong with my code?
Thanks in advance :)
// function within view to fetch data
fetchData: function()
{
console.log('fetchData')
// Assign scope.
var $this = this;
// Set the colletion.
this.collection = new BookmarkCollection();
console.log(this.collection)
// Call server to get data.
this.collection.fetch(
{
cache: false,
success: function(collection, response)
{
console.log(collection)
// If there are no errors.
if (!collection.errors)
{
// Set JSON of collection to global variable.
app.userBookmarks = collection.toJSON();
// $this.loaded=true;
// Call function to render view.
$this.render();
}
// END if.
},
error: function(collection, response)
{
console.log('fetchData error')
console.log(collection)
console.log(response)
}
});
},
// end of function
Model and collection:
BookmarkModel = Backbone.Model.extend(
{
idAttribute: 'lineNavRef'
});
BookmarkCollection = Backbone.Collection.extend(
{
model: BookmarkModel,
//urlRoot: 'data/getBookmarks.php',
urlRoot: 'http://' + app.Domain + ':' + app.serverPort + '/data/getBookmarks.php?fromCrm=true',
url: function()
{
console.log(this.urlRoot)
return this.urlRoot;
},
parse: function (data, xhr)
{
console.log(data)
// Default error status.
this.errors = false;
if (data.responseCode < 1 || data.errorCode < 1)
{
this.errors = true;
}
return data;
}
});
You can make the requests using JSONP (read about here: http://en.wikipedia.org/wiki/JSONP).
To achive it using Backbone, simply do this:
var collection = new MyCollection();
collection.fetch({ dataType: 'jsonp' });
You backend must ready to do this. The server will receive a callback name generated by jQuery, passed on the query string. So the server must respond:
name_of_callback_fuction_generated({ YOUR DATA HERE });
Hope I've helped.
This is a cross domain request - no can do. Will need to use a local script and use curl to access the one on the other domain.
Related
I want to first render a view with Backbone.js that displays an Article pulled from the server. I then want to mark this as "seen" and return the count of unseen messages to the router as it needs to be made available to other views.
So in my Router, I have:
getArticle: function (id) {
require(["app/models/article", "app/views/Article"], function (models, Article) {
var article = new models.Article({id: id});
article.fetch({
success: function (data) {
var articleView = new Article({model: data, message_count:that.message_count});
slider.slidePage(articleView.$el);
$.when(articleView.saveView()).done(function(data){
console.log('in when and data is ');
console.log(data);
});
},
error: function(){
console.log('failed to fecth artcie');
}
});
});
},
saveView() in the Article view is:
saveView: function(){
var viewDetails = [];
viewDetails.device_id = this.options.device_id;
viewDetails.article_id = this.model.id;
viewDetails.project_title = project_title;
var article_view = new models.ArticleView();
article_view.save(viewDetails,
{
success: function(data) {
var count = data.get('count');
console.log('in saveView() success and count is ');
console.log(count);
return count;
},
error: function(model, xhr, options){
console.log(xhr.responseText);
},
});
},
This hits a REST API, records the viewing of the article and then returns a count of unseen Articles. This results in a console output of:
in when and data is router.js:286 undefined router.js:287 in
saveView() success and count is Article.js:45 4
So, somehow, $.when is not working as it's not waiting for the Ajax request to send before executing the .done script. Any ideas?
You need to return a jQuery Deferred object for $.when to work properly:
return article_view.save(viewDetails,
{
success: function(data) {
var count = data.get('count');
console.log('in saveView() success and count is ');
console.log(count);
return count;
},
error: function(model, xhr, options){
console.log(xhr.responseText);
},
});
Backbone's save() method returns a jqXHR object which behaves the same way as a Deferred object in this case. Simply chain the return call as above. This should get $.when() to wait for the request to finish.
In the case, the actually conversation-simple have one function with all the values, but the function update every time if flows conversation.
I want create one function or other form to be able to capture all that data that is currently on the data.
In the case have Intents, context, entities, etc.
conversation.message(payload, function(err, data) {
if (err) {
return res.status(err.code || 500).json(err);
}
return res.json(updateMessage(payload, data));
});
});
The data inside updateMessage parameter have all I need, but if I create other function and try get this values, does not work.
In the case I use the values and get with app.js for open some REST webservice.
I try it:
function login (req, res) {
numberOrigin = null;
sessionid = null;
var dataLogin = {
data: { "userName":"xxxxx","password":"xxxxx","platform":"MyPlatform" },
headers: { "Content-Type": "application/json" }
};
client.registerMethod("postMethod", "xxxxxxxxxxxxxxx/services/login", "POST");
client.methods.postMethod(dataLogin, function (data, response) {
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
var re = /(sessionID: )([^,}]*)/g;
var match = re.exec(data);
var sessionid = match[2]
console.log(sessionid);
}
});
}
function openRequest(data, sessionid, numberOrigin ){
//console.log(data); dont show the values.. show the data response of login
var dataRequest = {
data: {"sessionID": sessionid,
"synchronize":false,
"sourceRequest":{
"numberOrigin":numberOrigin,
"description": JSON.stringify(data.context.email) } },
headers: { "Content-Type": "application/json" }
};
numberOrigin +=1;
client.post("xxxxxxxxxxxxxxxxxx/services/request/create", dataRequest, function (data, response) {
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
}
});
}
function updateMessage(res, input, data, numberOrigin) {
var email = data.context.email; // this recognize but this function is responsible for other thing
if (email === 'xxxxxxxxxxxx#test.com') {
console.log(data);
login(data);
openRequest(data, sessionid, numberOrigin)
}
}
In case, I just want get the values with my app.js for use inside REST. I got it with ajax but everything on the client side (index.html), and that made me show my credentials, so I decided to do it in REST for security my code..
If have some form to solved this, please let me know.
If have other form to do it, I'll be happy to know.
Thanks advance.
The issue is likely that you need to write to the response object res.. In the updateMessage function the response is passed in. In order for data to be sent back to the browser you need to write to the response. I have a demo app which calls the weather channel to get the weather based on an intent, similar to what you are trying to do with your login function. Please take a look at this code
https://github.com/doconnor78/conversation-simple-weather/blob/master/app.js#L130
You will need to pass the original res (response) object into the appropriate function and then write data to the response (res) once you get it from the third party service.
I have created a service with the purpose of accessing an API. I need to return data to my controller but am unsure how to do this as I completely new to sails.
My Service:
// API call to get the ID of contact within Get Response with email address
getContact: function(options) {
// establish connection to API
var api = new getResponse(apiKey, apiUrl);
var contact = api.getContactsByEmail(options.email, null, null, function (response) {
JSON.stringify(response);
console.log(JSON.stringify(response));
});
return contact;
},
I know the API call is working as when I log the response I get the correct response:
{"success":true,"data":{"error":null,"id":1,"result":{"sds":{"ip":null,"name":"Full Name","origin":"api","cycle_day":0,"email":"email#email.com","campaign":"id","created_on":"date","changed_on":null}}}}
My Controller:
index: function(req, res) {
var contact = GetresponseService.getContact({email: 'email#email.com'});
console.log(contact);
return res.send(contact);
}
I want to retrieve the ID value but when I log the value of contact I get undefined. I think my problem is related to the scope but not sure.
Can anyone point me in the right direction?
Because you are directly assigning a value from api.getContactsByEmail() which does not return a value.
By the nature of node.js, the function api.getContactsByEmail() gives you callback with the response. You have to get the value from within the anonymous callback function like this:
// API call to get the ID of contact within Get Response with email address
getContact: function(options) {
// establish connection to API
var api = new getResponse(apiKey, apiUrl);
var contact = "";
api.getContactsByEmail(options.email, null, null, function (response) {
contact = response;
JSON.stringify(response);
console.log(JSON.stringify(response));
return contact;
});
}
more ...
In my opinion, its better to return a callback instead of direct return of value.
// API call to get the ID of contact within Get Response with email address
getContact: function(options, callback) {
// establish connection to API
var api = new getResponse(apiKey, apiUrl);
var contact = "";
api.getContactsByEmail(options.email, null, null, function (response) {
contact = response;
JSON.stringify(response);
console.log(JSON.stringify(response));
if(typeof(callback) == "function")
callback(contact);
else
return contact; // return contact if there is callback func.
});
}
You can use it like:
index: function(req, res) {
var contact;
GetresponseService.getContact({email: 'email#email.com'}, function(contactResult) {
contact = contactResult;
console.log(contact);
return res.send(contact);
});
}
Everything looks like it should work, however I think you're running into an issue with this piece
var contact = api.getContactsByEmail(options.email, null, null, function (response) {
JSON.stringify(response);
console.log(JSON.stringify(response));
});
api.getContactsByEmail is asynchronous I assume, so this declarative statement won't work.
Instead declare contact and return it inside the callback, something like:
api.getContactsByEmail(options.email, null, null, function (response) {
JSON.stringify(response);
console.log(JSON.stringify(response));
var contact = response.contacts; //or however you access the contact(s) from the response variable
//You should also be watching for errors in your callbacks, but that's a different topic
return contact;
});
Read up on asynchronous calls in javascript and make sure you have a solid grasp on when data is accessible when using them.
This is the way I'm populating the attribute of my model:
this.model.set('questionAnswers', arrQuestions);
Now on submit, I check if model is valid:
if (this.model.isValid()) {
this.model.save(null, { success: this.gradingQuestionsSuccess, error: this.gradingQuestionsFailed });
}
Validations works like this:
validate: function (attr, options) {
var error = null;
if (attr.questionAnswers.length < this.cntQues) {
this.trigger('empty:answers');
error = 'Please answer all the questions.';
}
return error;
}
And service call is:
url: function () {
var url = Application.getConfig("url") + "/";
url += Application.getConfig("v2path3") + "/account/submitGradingQuestions";
}
return url;
}
The model is valid and the values are set in it on Submit, but it's not sending it in the Request Payload.
Can anyone please help me understand why this is happening? Thanks in advance!
Backbone does not observe the changed attributes and sync on save(null) automatically. What you need is pass attributes to Model.save method that makes set under the hood here or here depending on wait option's property. So you just need the following:
var data = {questionAnswers: arrQuestions};
this.model.save(data, {
success: this.gradingQuestionsSuccess,
error: this.gradingQuestionsFailed
});
You also don't need invoke validation manually because it's get invoked in save method also.
I'm trying to understand how a portion of backbone.js works. I have to fetch a collection of models once the app begins. I need to wait until fetch is complete to render each view.
I'm not 100% sure the best approach to take in this instance.
var AppRouter = Backbone.Router.extend({
routes: {
"": "home",
"customer/:id": "customer"
},
home: function () {
console.log("Home");
},
customer: function (id) {
if (this.custromers == null)
this.init();
var customer = this.customers.at(2); //This is undefined until fetch is complete. Log always says undefined.
console.log(customer);
},
init: function () {
console.log("init");
this.customers = new CustomerCollection();
this.customers.fetch({
success: function () {
console.log("success");
// I need to be able to render view on success.
}
});
console.log(this.customers);
}
});
The method I use is the jQuery complete callback like this:
var self = this;
this.model.fetch().done(function(){
self.render();
});
This was recommended in a Backbone bug report. Although the bug report recommends using complete, that callback method has since been deprecated in favor of done.
You can also do this with jquery 1.5+
$.when(something1.fetch(), something2.fetch()...all your fetches).then(function() {
initialize your views here
});
You can send your own options.success to the collections fetch method which runs only when the fetch is complete
EDIT (super late!)
From the backbone source (starting line 624 in 0.9.1)
fetch: function(options) {
options = options ? _.clone(options) : {};
if (options.parse === undefined) options.parse = true;
var collection = this;
var success = options.success;
options.success = function(resp, status, xhr) {
collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
if (success) success(collection, resp);
};
Note the second to last line. If you've passed in a function in the options object as the success key it will call it after the collection has been parsed into models and added to the collection.
So, if you do:
this.collection.fetch({success: this.do_something});
(assuming the initialize method is binding this.do_something to this...), it will call that method AFTER the whole shebang, allowing you trigger actions to occur immediately following fetch/parse/attach
Another useful way might be to bootstrap in the data directly on page load. This if from the
FAQ:
Loading Bootstrapped Models
When your app first loads, it's common to have a set of initial models that you know you're going to need, in order to render the page. Instead of firing an extra AJAX request to fetch them, a nicer pattern is to have their data already bootstrapped into the page. You can then use reset to populate your collections with the initial data. At DocumentCloud, in the ERB template for the workspace, we do something along these lines:
<script>
var Accounts = new Backbone.Collection;
Accounts.reset(<%= #accounts.to_json %>);
var Projects = new Backbone.Collection;
Projects.reset(<%= #projects.to_json(:collaborators => true) %>);
</script>
Another option is to add the following inside of your collections initialize method:
this.listenTo(this.collection, 'change add remove update', this.render);
This will fire off the render method whenever the fetch is complete and/or the collection is updated programmatically.
You Can Use on and Off Methods
if you want to add trigger method like suppose if you want on success you want to call render method so please follow below example.
_this.companyList.on("reset", _this.render, _this);
_this.companyList.fetchCompanyList({firstIndex: 1, maxResult: 10}, _this.options);
in Model js please use like
fetchCompanyList: function(data, options) {
UIUtils.showWait();
var collection = this;
var condition = "firstIndex=" + data.firstIndex + "&maxResult=" + data.maxResult;
if (notBlank(options)) {
if (notBlank(options.status)) {
condition += "&status=" + options.status;
}
}
$.ajax({
url: "webservices/company/list?" + condition,
type: 'GET',
dataType: 'json',
success: function(objModel, response) {
UIUtils.hideWait();
collection.reset(objModel);
if (notBlank(options) && notBlank(options.triggerEvent)) {
_this.trigger(options.triggerEvent, _this);
}
}
});
}