Handle logged in user model and view in backbone js - javascript

I have a login form in my backbone application and I would like to display a view with the status of the user. My login view looks like this:
var LoginView = Backbone.View.extend({
el: $("#login-form"),
events: {
'click button': 'login',
},
initialize: function () { },
login: function (event) {
var self = this;
event.preventDefault();
var url = '/api/auth/login';
$.ajax({
url: url,
type: 'POST',
data: this.$el.serialize(),
success: function () {}
});
}
});
What is the best way of saving the user object, display a login status view and restore it if the page is reloaded?

The whole process looks like this.
User hits the website.
A userSession model is created and assign to the application scope App.currentUser = new App.Models.UserSession()
Do fetch with currentUser App.currentUser.fetch()
According to the return, if there's an existing user session, display the user info. Else, show the login view.
Login view logic, in the success callback. App.currentUser.set(response)

Related

How to send values from Backbone to a CodeIgniter controller

I am making a small application form using Backbone.js and CodeIgniter but I am having problem with connection to controller.
Can anyone please provide me the full code for that?
My controller name is verfylogin. I have taken username and password from the user, and I have to pass it to the controller.
$(function(){
var Credentials = Backbone.Model.extend({});
var LoginView = Backbone.View.extend({
el: $("#login-form"),
events: {
"click #login": "login"
},
initialize: function(){
var self = this;
this.username = $("#username");
this.password = $("#password");
this.username.change(function(e){
self.model.set({username: $(e.currentTarget).val()});
});
this.password.change(function(e){
self.model.set({password: $(e.currentTarget).val()});
});
},
login: function(){
var username= this.model.get('username');
var password = this.model.get('password');
console.log(username,password);
}
});
window.LoginView = new LoginView({model: new Credentials()});
First, please read the Backbone documentation, look at the examples and test them to really understand how it works. Also, take a look at the Backbone.js tag wiki page.
It's irrelevant what is used for the API (backend), Backbone communicates with the backbend through a REST API which consist of URLs.
To link a Backbone model with a endpoint URL, override the urlRoot property.
var Credentials = Backbone.Model.extend({
// Specify the endpoint URL here
urlRoot: "api/endpoint" // relative
// urlRoot: "http://example.com/api/endpoint" // or absolute
});
Then, use the Backbone view's events hash to manage events within the view. Avoid manually binding jQuery events.
var LoginView = Backbone.View.extend({
events: {
"click #login": "login",
"change #username": "onUsernameChange",
"change #password": "onPasswordChange"
},
initialize: function() {
// create the model here
this.model = new Credentials();
// cache jQuery object within the view
this.$username = this.$("#username");
this.$password = this.$("#password");
},
login: function() {
// just call save to make a post request with the data.
this.model.save();
},
onUsernameChange: function(e) {
this.model.set({ username: this.$username.val() });
},
onPasswordChange: function(e) {
this.model.set({ password: this.$password.val() });
}
});
var loginView = new LoginView({ el: "#login-form" });
That way, the context (this) is available in the events callbacks. Avoid hard-coding the el property and prefer passing it on the initialization of a new view instance.
Handling JSON data posted to a CodeIgniter controller
Since I don't use CodeIgniter, I will refer you to other resources.
Working with restful services in CodeIgniter
Retrieve JSON POST data in CodeIgniter
Post JSON to Codeigniter controller
Get JSON response In Codeigniter
Code Igniter - How to return Json response from controller

Redirect or render another view on event

I'm building a little CRUD app in Backbone, and I'm stuck a little with a need to redirect from one view to another. My app consists of a layout view, in which other views are rendered, and a router. Here it is:
var router = Backbone.Router.extend({
routes: {
'': 'home',
'resumes/:id': 'showResume'
},
home: function () {
// renders a index view with my collection
this.layout.render(new ResumeList({collection: resumes});
},
showResume: function () {
if (!this.fullResume) {
this.fullResume = new FullResume({model: new Resume()});
}
// allowing to navigate via url with model id
this.fullResume.model.set('id', id).fetch({
context: this,
success: function () {
this.layout.render(this.fullResume);
}
});
}
});
Then, in my FullResume view I've got a delete event, which destroys the model. Here it goes:
var FullResume = Backbone.View.extend({
// tagName and other stuff
events: {
// other events
'click #delete': 'deleteResume'
},
// initialize, render and other functions
deleteResume: function () {
this.model.destroy({
success: function (res) {
console.log('DELETE model' + res.toJSON().id);
},
error: function () {
console.log('Failed to DELETE');
}
});
}
});
The function above works perfectly and deletes the model, but after deleting the model it still remains on it's view until I navigate somewhere manually. I read a bit and tried to manage how to render the main view after this event or redirecting to it, but didn't succeed a much.
You are looking for the http://backbonejs.org/#Router-navigate function with the trigger option set to true.
Here's an example: http://jsfiddle.net/x3t7u5p0/
Clicking on "Home" or "About" links will change the view, however I've added a delayed programmatic view change, when the About view renders, it will switch back to Home after the delay
render: function () {
this.$el.html(this.template);
_.delay(function() {
appRouter.navigate('home', {trigger: true});
}, 500);
}

Refresh page to see content

I've created a Rails app using Backbone, but I've run into a small but annoying problem. When a user goes to his profile and then back to the frontpage the frontpage is empty and I have to refresh it in order to show the content of the backbone view.
In my Movieseat.Routers.Movieseats I have:
routes:
'': 'index'
initialize: ->
#movieSeats = new Movieseat.Collections.Movieseats()
#movieSeats.fetch()
#searchResults = new Movieseat.Collections.Moviesearch()
index: ->
view = new Movieseat.Views.MovieseatsIndex(collection: #movieSeats)
$('#container').html(view.render().el)
Any idea on why users have to refresh to see the frontpage?
I don't know CoffeeScript but the fetch() method takes a success callback where you can ensure the collection has loaded. In your index you're creating a new view passing the #movieSeats collection but the collection may have not been loaded by that time. Try the following:
{
routes: {
'': 'index'
},
initialize: function() {
this.movieSeats = new Movieseat.Collections.Movieseats();
},
index: function() {
var self = this, view;
this.movieSeats.fetch({
success: function(collection) {
view = new Movieseat.Views.MovieseatsIndex({ collection: collection })
$('#container').html(view.render().el)
}
});
}
}
However, you might want to "bootstrap" your collection like is shown on the Backbone docs: http://documentcloud.github.io/backbone/#FAQ-bootstrap

How to write data received from the server after .fetch() in model and passed to template?

Good day! I'm new in backbone and i writing a simple little application based backbone + jquerymobile.
When I get data from the server, I need to properly transfer the data to the view, where they are passed to the template. Because the .fetch() asynchronous, i cant just pass in render my model. How can I do so that would after .fetch() data received from the server, written in the model and then passed to the template?
//template
<script type="text/html" class="template" id="profile-form">
<div data-role="header">
<h3>Step 4</h3>
Home
logout
</div>
<div data-role="content">
<h2 class="ui-li-heading"><%= username %></h2>
<p class="ui-li-desc"><strong><%= phone %></strong></p>
</div>
</script>
// model
var UserInfo = Backbone.Model.extend({
url: appConfig.baseURL + "users/",
});
// routes
profileInfo: function () {
var user = new UserInfo()
this.changePage(new ProfilePageView({ model: user }));
},
// view
var ProfilePageView = Backbone.View.extend({
initialize: function () {
this.template = $.tpl['profile-form'];
},
render: function (eventName) {
$(that.el).html(that.template());
return this;
}
});
I trying to add this part in my render in view. Its works, but my styles are not working.
I'm not quite sure that I did the right thing by putting fetch in render, can advise how to do correctly?
var that = this
this.model.fetch({
data: $.param({email: localStorage.getItem('user_email')}),
type: 'POST',
success: function (response) {
$(that.el).html(that.template(JSON.parse(JSON.stringify(response))));
}
});
Use the built-in events to decouple everything. Fetching is one step, updating is distinct. In your view do:
initialize: function () {
this.template = $('#profile-form').html();
this.listenToOnce(this.model, 'sync', function(){
this.render();
//this.listenTo(this.model, 'change', this.render, this);
}, this);
},
Every time the model has the set method called (and some attribute changes) it will trigger a change event. The listenTo method will run a callback when that happens. Another event you might want is sync which is called after a successful fetch. Sometimes you might need listenToOnce if you only want to render on the first sync and then control it yourself after that.
Your template probably needs its parameters passed in too:
render: function(){
$(this.el).html(_.template(this.template, this.model.toJSON()));
return this;
}
In terms of when to fetch, that's up to you a bit. You could fetch regularly or only when someone routes to that page. In the code you give I would do something like:
profileInfo: function () {
var user = new UserInfo();
user.fetch();
this.changePage(new ProfilePageView({ model: user }));
}

Backbone Boilerplate - fetch method don't refresh collection

is my first question here, so I please about some patience and forgive my english:)
When I type link in browser address bar, all is OK. But when I do this inside browser by clicking element, collection is empty. But the main problem is there is always the same response from server, but fetch "dont load" any items, so view render empty collection.
I use Backbone Boilerplate,
Browser.Views.Catalog - it is Backbone.View
Browser.Catalog - it is of Backbone.Collection
My router:
var Router = Backbone.Router.extend({
routes: {
'' : 'browse'
},
refreshCatalog: function(folder){
app.layout.setViews({
"#catalog" : new Browser.Views.Catalog({
collection: app.catalog
})
}).render();
},
browse: function(folder){
app.catalog = new Browser.Catalog();
app.folders.fetch({
error: function() { console.log(arguments); },
success: this.refreshFolders(folder),
data: $.param({folder: folder}),
cache:false
});
//app.catalog = new Browser.Catalog();
app.catalog.fetch({
error: function() { console.log(arguments); },
success: this.refreshCatalog(folder),
data: $.param({folder: folder}),
cache:false
});
},
I belive you should set the catalog in the initialize function
app.catalog = new Browser.Catalog();
should go in here ( add this function)
initialize: function (options) {
app.catalog = new Browser.Catalog();
}
the initialize function is called when the page is loaded so when browsing to #catelog it will have been set http://backbonejs.org/#Router-constructor

Categories

Resources