Backbone Router has no method navigate - backbone.js

Just wondering why my router has no method navigate?
I have new App.Router; called properly. And in my view I try to call my index view like so:
addTrip: function(e){
e.preventDefault() ;
//Adding to collection
var newTrip = this.collection.create({
title: this.$('#new_trip #title').val(),
where: this.$('#new_trip #where').val(),
desc: this.$('#new_trip #desc').val(),
rating: this.$('#new_trip .active').text()
}, { wait: true }) ;
if(newTrip.validationError){
this.errorReport(newTrip.validationError) ;
}
this.clearForm() ;
//Navigate to home route
App.Router.navigate('', true) ;
}
I get the following error in Chrome Dev Tools:
Uncaught TypeError: Object function (){ return parent.apply(this, arguments); } has no method 'navigate'
I even tried to call navigate from the console and it doesnt seem to work either.
What am I doing wrong?

You should call navigate on your router object. It seems you are calling it on the class itself.
App.myRouter = new Backbone.Router() //or if you have your own base router class App.myRouter = new App.Router()
myRouter.navigate('', true);

Related

Protractor : Error: Error while waiting for Protractor to sync with the page: "window.angular is undefined. If i create new object of PageObject

I am trying to create a object of page object into spec and i am getting the error.
dashboard.pageObject.js
/*global exports,console*/
module.exports = function(){
this.dashboarurl = 'http://localhost:2525/ars-webapp/';
this.createNewReport_Clickhear = element(By.xpath("//a[contains(.,'Click Here')]"));
this.reportInputModel = element(by.model('reportDefCntrl.reportDef.reportname'));
this.reportDescriptionModel = element(by.model('reportDefCntrl.reportDef.reportdesc'));
this.templateListSelect = element(By.xpath("//select[#id='template-list-select']")).click();
this.selectAlarmDashboarTemplate= element(By.xpath("//option[contains(#value,'number:2')]"));
this.durationOfAlarmTemplate = element(By.xpath("//span[#class='ui-select-placeholder text-muted ng-binding']"));
this.duration_Daily = element(By.xpath("//span[contains(.,'Daily')]"));
this.addObject = element(By.xpath("//button[#data-ng-click='reportDefCntrl.addLogObjects()']"));
this.searchInput = element(By.xpath("//input[#type='search']"));
this.searchButton = element(By.xpath("//button[contains(.,'Search')]"));
this.selectAllButton = element(By.xpath("//button[contains(.,'SelectAll')]"));
this.addObjectButton = element(By.xpath("//button[#data-ng-click='addLogObjectsCntrl.submitObjects()']"));
this.saveButton = element(By.xpath("//button[contains(.,'Save')]"));
}
Specfile is
/global require,console/
var Dashboard = require('../pageObjects/dashboard.pageObject.js');
var dashboard = new Dashboard();
describe('angularjs homepage todo list', function() {
it('should add a todo', function() {
browser.get(dashboard.dashboarurl);
}
if i skip the line
var dashboard = new Dashboard();
and provide
browser.get('http://localhost:2525/ars-webapp/');
instead of
browser.get(dashboard.dashboarurl);
it's working .
but i can't use feature of page object.
if i use
var dashboard = new Dashboard();
so i am getting error
E/launcher - Error while waiting for Protractor to sync with the page:
"window.angular is undefined. This could be either because this is a
non-angular page or because your test involves client-side navigation,
which can interfere with Protractor's bootstrapping. See
http://git.io/v4gXM for details"
Oh Man .. found it !!.. Everything was fine in your code. You know what .. The problem was .. you had a click() in this line this.templateListSelect = element(By.xpath("")).click() in your file - dashboard.pageObject.js
Since you have a require() first .. The dashboard file is executed first and click() is trigerred even before browser.get() and thats the reason you were seeing that error

React Native FBSDK onLoginFinished push to new screen

I'm somewhat new to using react native and I'm trying to implement Facebook login with my app using the react native fbsdk.
I've gotten it to the point where it will ask for permissions from the user's Facebook profile, then return to the app with a success alert message. Instead of displaying the alert onLoginFinished, I want to push to a new screen.
This is my login button code in the main constructor class:
constructor(props){
super(props);
this.goToNewPage = this.goToNewPage.bind(this);
const infoRequest = new GraphRequest(
'/me',
{parameters: {
fields: {
string: 'email,first_name,last_name,id,gender' // what you want to get
}
}},
this._responseInfoCallback,
);
Login = React.createClass({
render: function() {
return (
<View >
<LoginButton
navigator={this.props.navigator}
style = {{marginLeft:55, marginRight:55, height:50, width:300}}
onLoginFinished={
(error, result) => {
if (error) {
alert("Login failed with error: " + result.error);
} else if (result.isCancelled) {
alert("Login was cancelled");
} else {
alert("Login was successful with permissions: " + result.grantedPermissions)
new GraphRequestManager().addRequest(infoRequest).start();
this.goToNewPage;
}
}
}
onLogoutFinished={() => alert("User logged out")}
/>
</View>
);
}
});
} //closes constructor
_responseInfoCallback(error: ?Object, result: ?Object) {
if (error) {
alert('Error fetching data: ' + error.toString());
} else {
alert('Success fetching data: ' + result.toString());
console.log(result);
}
}
goToNewPage(){
console.log("Hello from go to new page function");
this.props.navigator.push({
id: 'newPage',
name: 'Going To New Page',
});
}
But after the success alerts are displayed, it does not push to the new page. It seems like this.props.navigator is not recognized in my Login class, and I'm not sure why. Any help at all would be greatly appreciated
Turns out the problem was that I declared the login class in my constructor. Moving it to a componentWillMount function fixed it for me!
Currently you are calling goToNewpage() method in error, result block of LoginButton component and in any kind of block we can't access current class reference "this" directly because it loses its reachability.
Then you should create a global variable for this component as
var _this;
and assign current reference of class in component constructor like:
_this = this;
and should use _this.props.navigator.push in place of this.props.navigator.push within your goToNewpage() method. Thanks!

How to log all properties from an object in google script

I am trying to get all the properties of array object routes to be logged 1 by 1, however, it's giving undefined error.
function testRoutes () { //Calling the maps API and new direction finder.
var directions = Maps.newDirectionFinder()
.setOrigin('Kharadar, Karachi')
.setDestination('Guru Mandir, Karachi')
.setMode(Maps.DirectionFinder.Mode.DRIVING) //By default driving.
.getDirections();
//We have got all the directions now from origin to destination in test variable.
// var route = directions.routes[0].legs[0].steps[1];
// var route2 = directions.routes[0];
var route = directions.routes;
for (var propt in route) {
Logger.log(route[0].propt);
}
//Logger.log(route[0].summary);
}
If you loop through properties of variable route it should be
for (var propt in route) {
Logger.log(route[propt]);
}

Trouble running underscore templates

I'm unable to run render HTML from an Underscore template. Here's the code and the error:
//Code
class QuestionView extends Backbone.View {
template:(data:any) => string = null;
$el = $root;
constructor(options?:any, question?:Question) {
super(options);
this.model = question;
var q = this;
require(["text!add-new-question.html"],
function (html) {
q.template = _.template(html);
}
);
}
render() {
var data = this.model.toJSON();
var html = this.template(data);
this.$el.html(html);
return this;
}
}
class SurveyView extends Backbone.View{
tagName = "div";
template:(data:any) => string = null;
$el = $root;
constructor(options?:any, survey?:Survey){
super(options);
this.template = _.template("<div ><%= enlistQuestions %></div>");
}
enlistQuestions():string{
var questions = "";
_.each(this.collection.models, function(question:Question){
var view = new QuestionView(null,question);
questions += view.template(view.model.toJSON()); // This is line for which the error is shown.
});
return questions;
}
}
//Error
Uncaught TypeError: Property 'template' of object #<QuestionView> is not a function Main.ts:63
(anonymous function) Main.ts:63
j.each.j.forEach underscore.js:79
SurveyView.enlistQuestions Main.ts:61
SurveyView.render Main.ts:69
SurveyView Main.ts:56
(anonymous function) Main.ts:80
Looks like you are using the "text" AMD loader plugin. If not, disregard this answer.
This plugin loads the resource asynchronously and the function supplied to the require statement is called back after the file is loaded.
It appears that the Main is attempting to use the template property on the QuestionView instance before the callback has chances to create it, hence the error.
The text module creates the XHR object and invokes open set the async flag to true. You need to set this flag to false. The only way this is possible is to use the onXhr callback and invoke OPEN again setting the async flag to false.
requirejs.config({
config: {
text: {
onXhr: function (xhr, url) {
// This callback is invoked AFTER open but before send.
// Call open again with the async flag turned off.
// Not this will also clear any custom headers
xhr.open('GET', url, /*async*/ false);
// xhr.setRequestHeader('header', 'value');
}
}
}
});
As noted above, any custom HTTP header added by the text module will be cleared when you re-invoke open, but looking at their code there doesn't appear to be any way of supplying extra headers into their 'get' function.

Backbone collection.create not creating the model locally

I gave up finally. I have struggling to get this one to work but no luck. I simply have a collection.create call like this:
var createData = {
full_name : full_name,
email : email,
role_id : role_id
};
var that = this;
app.collections.teamMembers.create(createData,{
wait: true,
success : function(){
log("in success")
},
error : function(a,b,c){
log("in error")
}
})
The server is PHP and it returns the result like this:
header('Content-type: application/json');
echo json_encode(array(
"data" => $data,
"meta" => $meta
));
In the above, the $data is actually the array("attr"=>"val", ...) which matches exactly how the model for this collection is defined.
The problem is that since I am not returning directly a JSON object similar to the original model, but using namespacing (data/meta), I use model.parse on the model like this:
parse : function(response){
log(response, "inside model parse, this is the response from server")
return response.data;
},
ISSUE: The model doesn't get created on the client end. No 'add' event is fired. I am also using the wait:true option.
However, the model gets created on the local if:
- I don't use wait:true
- I use wait true but return the exact JSON model from server, with no name spacing.
I WANT to use wait:true as well as namespacing. Please help :(
Finally I was able to fix it, I was overriding backbone collections and models in my bootstrap to have a loading state which I am not using anyway. So I commented out that whole code. Now it works fine. this was the code in my bootstrap that I commented out:
// OVERRIDINGS AND SETTINGS
//----------------------
// Adding close method to all views
Backbone.View.prototype.close = function() {
if (this.onClose) {
this.onClose();
}
_.each(this.childViews, function(childView){
childView.close();
delete childView;
})
this.remove();
this.unbind();
};
// Adding loading state to every model and collection
Backbone.Collection.prototype.loading = false;
Backbone.Model.prototype.isLoading = false;
// Set isLoading to true when fetch starts
var oldFetch = Backbone.Collection.prototype.fetch;
Backbone.Collection.prototype.fetch = function(options) {
this.isLoading = true;
oldFetch.call(this, options);
}
Backbone.Model.prototype.fetch = function(options) {
this.isLoading = true;
oldFetch.call(this, options);
}
// Turn off isLoading when reset
Backbone.Collection.prototype.on('reset', function(){
this.isLoading = false;
})
Backbone.Model.prototype.on('reset', function(){
this.isLoading = false;
})

Resources