Iam learning Backbone JS, why my below code not displaying in browser? I even used routers, but still not displaying in browser. Please tell me what went wrong. BTW, output just displaying in Console only. Sorry if its dumb query.
<html>
<head>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.1.1/css/bootstrap.min.css">
<script type="text/javascript">
/*$.getJSON('api/users/1',function(data){
console.log(data);
});*/
</script>
</head>
<body>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<script type="text/javascript">
var TodoItem = Backbone.Model.extend({
toggleStatus: function(){
if(this.get('status') == 'incomplete'){
this.set({'status':'complete'});
} else {
this.set({'status':'incomplete'});
}
}
})
var TodoView = Backbone.View.extend({
template: _.template('<h3> ' +'<input type=checkbox ' +'<% if(status === "complete") print("checked") %>/>' +' <%= description %></h3>'),
render: function(){
this.$el.html(this.template(this.model.toJSON()));
},
events: {
'change imput': 'toggleStatus'
},
toggleStatus : function(){
this.model.toggleStatus();
}
})
var todoItem = new TodoItem({ description: 'Pick up milk', status: 'incomplete', id: 1 });
var todoView = new TodoView({model: todoItem});
console.log(todoView.el);
var Router = Backbone.Router.extend({
routes: {
'': 'home'
}
});
var router = new Router();
router.on('route:home' , function(){
todoView.render();
});
Backbone.history.start();
</script>
</body>
</html>
Every view should render in one of this fashions , when You want create new element, specify tagName, className and id, and when need an element to append view to It you should specify el to select it (jquery selects it). Next issue of Your code is that you do not return this in the render function. when You have nested views , You should return this.
I have tested it in this bin
http://jsbin.com/jefuyuxanu/2/edit
Your TodoView isn't appended into DOM .
set "el" attribute for your view
var TodoView = Backbone.View.extend({
el:'body',
template: _.template('<h3> ' +'<input type=checkbox ' +'<% if(status === "complete") print("checked") %>/>' +' <%= description %></h3>'),
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
},
events: {
'change imput': 'toggleStatus'
},
toggleStatus : function(){
this.model.toggleStatus();
}
})
Related
Hello I am using google api to sign in to my web application . Its working fine . But the problem is the sigin is automatic in my application, but for signup i want start that process after user check the term&condition and the process will start.
below is the JS code:
var googleUser = {};
var auth2;
var startApp = function() {
gapi.load('auth2', function(){
auth2 = gapi.auth2.init({
client_id: 'XXXXXX',
});
$("body").on("click", ".googlesignin", function(e){
if($('#terms').is(":checked")){
termsvalue='1';
$("#termsValidation").hide();
$("#termsValidation").attr("data-hint", $("").text());
attachSignup(document.getElementById("googlesignin"));
}
else
{
e.preventDefault();
termsvalue='';
$("#termsValidation").show();
$("#termsValidation").attr("data-hint", "Please agree by clicking checkbox");
return false;
}
});
});
};
function attachSignup(element) {
auth2.attachClickHandler(element, {},
function(googleUser) {
var profile = googleUser.getBasicProfile();
console.log(googleUser.getAuthResponse().id_token);
var googleurl = "https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=" + googleUser.getAuthResponse().id_token
$.getJSON(googleurl, function(result){
$("#rfirstname").val(result.given_name);
$("#remail").val(result.email);
$("#googlePicture").val(result.picture);
$("#google_id").val(result.sub);
});
}, function(error) {
parsed_error = JSON.stringify(error, undefined, 2);
parsed_error = JSON.parse(parsed_error);
if(popup_closed_by_user!='popup_closed_by_user'){
alert(popup_closed_by_user);
}
});
};
startApp();
this is my html:
<html>
<head>
<meta name="google-signin-client_id" content="XXXXXX">
<script src="https://apis.google.com/js/api:client.js"></script>
</head>
<body>
<div>
<input type="checkbox" id="terms">
<div id="googlesignin" class="googlesignin"><img alt="" src="google.png" style="vertical-align: initial;"></div>
</div>
</body>
</html>
In first click it's not working but after that it's working fine. need help. Thanks in advance.
I'd suggest to try to comment last line of startApp and add below hooks for when jQuery is loaded.. like this, hope this will help
// startApp();
(function($){
$(document).ready(function(){
startApp();
}); // - end DOCREADY
})(jQuery);
I have a SPA using knockout JS for data binding and sammy for routing. I have a deck of cards that I am trying to have a dynamic routing to. My problem is that it doesn't work when I try to set a knockout observable from the routing function in sammy.
My HTML, where I try to bind the name of the deck, looks like this:
<!-- Create Deck -->
<div id="createDeck" class="page" style="display:none;">
<input type="text" class="form-control" placeholder="Untitled Deck..." data-bind="value: $root.deck.name" />
</div>
<script type="text/javascript" src="lib/jquery-1.9.1.js"></script>
<script type="text/javascript" src="lib/knockout-2.3.0.js"></script>
<script type="text/javascript" src="lib/bootstrap.min.js"></script>
<script type="text/javascript" src="lib/sammy.js"></script>
<script type="text/javascript" src="js/Models/Deck.js"></script>
<script type="text/javascript" src="js/Models/Card.js"></script>
<script type="text/javascript" src="js/ViewModels/DeckViewModel.js"></script>
<script type="text/javascript" src="js/ViewModels/CardViewModel.js"></script>
<script type="text/javascript" src="js/routing.js"></script>
The Deck.js and DeckViewModel.js looks like below
function Deck(deckid, name, cards) {
var self = this;
self.id = deckid;
self.name = name;
self.cards = cards;
}
function DeckViewModel(deck, cards) {
var self = this;
self.deck = ko.observable(deck);
self.cards = ko.observableArray(cards);
self.goToCard = function (card) { location.hash = card.deckid + '/' + card.id };
}
// Bind
var element = $('#createDeck')[0];
var deckView = new DeckViewModel(null, null);
ko.applyBindings(deckView, element);
Finally, in my routing I try to create a new Deck, like this:
// Client-side routes
(function ($) {
var app = $.sammy('#content', function () {
this.get('#deck/:id', function (context) {
showPage("createDeck", ": Create Deck");
console.log(this.params.id);
deckView.deck = new Deck(1, "test", null);
console.log(deckView.deck);
});
});
$(function () {
app.run('#/');
});
})(jQuery);
function showPage(pageID, subHeader) {
// Hide all pages
$(".page").hide();
// Show the given page
$("#" + pageID).show();
// change the sub header
$("#subHeader").text(subHeader);
}
As you can see, I'm trying to create a test deck with the name 'test', but the binding <input type="text" class="form-control" placeholder="Untitled Deck..." data-bind="value: $root.deck.name" /> seems to bind the letter 'c'.
I'm at a loss, please help.
I tried to make a jsfiddle to demonstrate my problem
In your code the value assignment is not correct unless you are using Knockout-es5 plugin. here is the correct code
var app = $.sammy('#content', function () {
this.get('#deck/:id', function (context) {
showPage("createDeck", ": Create Deck");
console.log(this.params.id);
deckView.deck(new Deck(1, "test", null));
console.log(deckView.deck());
});
});
The way I've done this before is to define my Sammy() routes within the ViewModel. Shorter example for brevity:
(function($) {
function ViewModel() {
var self = this;
self.deckId = ko.observable(null);
Sammy(function() {
this.get('#/deck/:deckId', function(context) {
self.deckId(this.params.deckId);
});
});
}
$(function() {
ko.applyBindings(new ViewModel());
});
})(jQuery);
That way you can access your observables, etc, via self.
I'm using Backbone.js 0.9.10, 1.4.4 Underscore.js.
When I call my html page there is no javascript error and the console shows that the collection was iterated.
However, the browser does not show my html I get the blank page. I log the result of html on console and appears without replacing variables of model ​​by json, like that:
(I retired the signals (< >) in the tags to show that the html template that appears on console.)
my html come from view =
p
a href="#" id="remove-button" >Remover este Post/a
/p
h2 /h2
p /p>
//HTML
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Backbone COLLECTION</title>
<script src="../js/jquery/jquery-1.8.3.js" type="text/javascript" charset="utf-8">
</script>
<script src="../js/backbone/underscore.js" type="text/javascript" charset="utf-8">
</script>
<script src="../js/backbone/backbone.js" type="text/javascript" charset="utf-8">
</script>
<script src="../js/mvc/PostModel.js"></script>
<script src="../js/mvc/PostView.js"></script>
<script src="../js/mvc/PostCollectionView.js"></script>
<script src="../js/mvc/PostCollection.js"></script>
<script>
$(document).ready(function() {
var postList = new PostList();
var postCollectionView = new PostCollectionView({collection:postList});
postList.fetch();
});
</script>
</head>
<body>
<script type="text/template" id="post-template">
<p>
Remover este Post
</p>
<h2><%=title%></h2>
<p><%=text%></p>
</script>
</body>
</html>
//VIEW
var PostView = Backbone.View.extend({
events: {
"click #remove-button": "removePost"
},
initialize: function() {
_.bindAll(this, 'render', 'removePost', 'refresh');
this.template = _.template($('#post-template').html());
this.model = new PostModel();
this.model.on("change", this.render, this);
this.model.on("destroy", this.refresh);
},
render: function() {
console.log('PostView - render ');//ok
var template = this.$el.html(this.template(this.model.toJSON()));
return this;
},
removePost: function() {
this.model.destroy();
},
refresh: function() {
this.model.clear({silent: true});
this.model.fetch();
}
});
//MODEL
var PostModel = Backbone.Model.extend({
defaults : function(){
return {
//some
title: [],
text: []
}
}
});
//COLLECTION
var PostCollectionView = Backbone.View.extend({
initialize: function(){
this.collection.on('add', this.addOne, this);
this.collection.on('reset', this.addAll, this);
},
addOne: function(modelItem){
var postView = new PostView({model: modelItem});
console.log('my html come from view = ' + postView.render().$el.html());
this.$el.append(postView.render().$el.html());
},
addAll: function(){
this.collection.forEach(this.addOne, this);
},
render: function(){
this.addAll();
}
});
//Collection with URL
var PostList = Backbone.Collection.extend({
url: 'http://www.mysystem.com/newproject/project/cadTarefas/recuperarListaTeste',
model: PostModel
});
//My JSON
[{"title":"titulo_1","text":"texto_1"},{"title":"titulo_2","text":"texto_2"},
{"title":"titulo_3","text":"texto_3"},{"title":"titulo_4","text":"texto_4"},
{"title":"titulo_5","text":"texto_5"},{"title":"titulo_6","text":"texto_6"},
{"title":"titulo_7","text":"texto_7"},{"title":"titulo_8","text":"texto_8"},
{"title":"titulo_9","text":"texto_9"},{"title":"titulo_10","text":"texto_10"}]
The one thing I don't see in any of your code is where PostCollectionView's element is attached to the DOM. It should either have a static declaration, i.e.
var PostCollectionView = Backbone.View.extend({
el: $('#somediv'),
Or an external one,
$(document).ready(function() {
var postList = new PostList();
var postCollectionView = new PostCollectionView({collection:postList, el: $('#somediv')});
Or your controller is responsible for attaching the dynamically allocated one to the DOM after the View has been initialized. One of those has to be true.
Secondly, in PostView, after you pass in an existing model, you destroy it with the line this.model = new PostModel();, which overwrites the object-local reference passed in with a new, blank model, which is why you're not seeing anything.
Try change string in render view
var template = this.$el.html(this.template(this.model.toJSON()));
to string
this.$el.html(this.template(this.model.toJSON()));
I am trying to learn to use Knockoutjs but I am facing a problem
this is the scenario:
I have a page where I define a Knockoutjs viewModel as follow
$(document).ready(function () {
var viewModel = {
selectedColumns: ko.observableArray()
};
ko.applyBindings(viewModel);
});
Now with an Ajax request I add to the page a checkbox which I want to bind to the viewModel
<input type='checkbox' id='someId' data-bind='attr: { value: 'someValue' }, checked: $root.selectedColumns'>
$(document).ready(function() {
ko.applyBindings(viewModel, document.getElementById(someId));
});
but I always get
Error: ReferenceError: viewModel is not defined
Source File: http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
I've created a test page where everything is on one page and it works
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Home Page</title>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'></script>
<script src="../../Scripts/knockout-2.1.0.debug.js" type="text/javascript"></script>
<script type="text/javascript">
var count = 0;
var viewModel = {
selectedPeople: ko.observableArray()
};
$(document).ready(function () {
ko.applyBindings(viewModel);
});
function AddAnotherCheckbox(){
var id = "checkbox" + count;
var checknox = count + " <input type='checkbox' id='" + id + "' data-bind='attr: { value: \"" + count + "\" }, checked: $root.selectedPeople'><br/>";
$("#container").append(checknox);
count++;
$(document).ready(function() {
ko.applyBindings(viewModel, document.getElementById(id));
});
}
</script>
</head>
<body>
<input type="button" onclick="AddAnotherCheckbox()"/>
<div id="container"></div>
<br/>
<br/>
<br/>
<span data-bind="text: selectedPeople"></span>
</body>
</html>
But I can't make it working using partial view
Could you explain to me what's the problem and how can I solve it?
thanks
Description
This is not about Knockout, it's about JavaScript in general.
Your Testcode works because you have defined the viewModel outside of $(document).ready
This is a other scope.
Compare theese to jsFiddles
This does not work (your scenario)
This works
Sample
This does not work
$(document).ready(function () {
var viewModel = {
someThing : "Test"
};
});
$(document).ready(function () {
alert(viewModel.someThing);
});
This will work
var viewModel;
$(document).ready(function () {
viewModel = {
someThing : "Test"
};
});
$(document).ready(function () {
alert(viewModel.someThing);
});
More Information
Explaining JavaScript Scope And Closures
​
<head>
<title></title>
<script src="javascript/vendor/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="javascript/vendor/underscore.js" type="text/javascript"></script>
<script src="javascript/vendor/backbone.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript" >
var MyApp = (function(_, Backbone){
var myApp = {};
var initializers = [];
myApp.addInitializer = function(callback){
var initializer = {
obj: this,
callback: callback
}
initializers.push(initializer);
};
myApp.initialize= function(){
_.each(initializers, function(initializer){
initializer.callback.call(initializer.obj);
});
};
// the event aggregator
myApp.vent = _.extend({}, Backbone.Events);
// the other app initialization code ...
return myApp;
})(_, Backbone);
var MyModule = (function(MyApp, Backbone){
var MyView = Backbone.View.extend({
initialize: function(){
MyApp.bind("some:event", this.someCallback, this);
},
someCallback: function(){
alert("I'm Doing Stuff!!!");
}
});
// ... other code, including MyApp.addInitializer
})(MyApp, Backbone);
var AnotherModule = (function (MyApp, Backbone) {
var anotherModule = {};
anotherModule.SomeFunction = function () {
MyApp.trigger("some:event");
//alert("Hello");
};
return anotherModule;
})(MyApp, Backbone);
// kick it all off and show the alert box
//$(function(){
// MyApp.initialize();
// AnotherModule.SomeFunction();
//});​
$(function () {
MyApp.initialize();
AnotherModule.SomeFunction();
});
</script>
</body>
I am getting error on this line MyApp.trigger("some:event"); . I copied the code from following link
URL: http://lostechies.com/derickbailey/2011/11/17/introduction-to-composite-javascript-apps/
Can you help me using modules two or more and each of them have multiple views. I need to communicate them using backbone as the above URL did.
Thanks.
I tried to solve this in different ways but kept ending up with the following solution. The solution involves writing my code in modules and using marionette modules and vent to communicate with them. Marionette helped me a lot and I hope the different features further in my development.
index.html
<script type="text/javascript">
$(function () {
//var myModule = MyApp.module("MyModule");
// console.log(MyApp.MyModule.someData); //=> public data
MyApp.OrganizerModule.someFunction(); //=> public data
//var LayOutModel = new MyApp.ShellModule.LayOut();
var LayoutView = new MyApp.ShellModule.LayoutView();
LayoutView.render();
var Explorer = new MyApp.OrganizerModule.ExplorerView();
});
</script>
The following templates are used:
<script id="layout_temp" type="text/template">
<div id="layout">
<div id="header">
header
</div>
<div id="container">
<div id="center" class="column">
center
</div>
<div id="left" class="column">
left
</div>
<div id="right" class="column">
right
</div>
</div>
<div id="footer">
footer
</div>
</div>
</script>
<script id="Explorer" type="text/template">
<div > start :
<button>Say hello</button>
</div>
</script>
Here is the Module definition and the subscription of the event using Marionette
MyApp.module("ShellModule", function (ShellModule, MyApp, Backbone, Marionette, $, _) {
ShellModule.LayoutView = Backbone.View.extend({
initialize: function () {
//Backbone.ModelBinding.call(this);
alert("Hello2");
MyApp.vent.on("toolClick_Event", function (cat) {
alert("test toolClick_Event fired");
});
}
// , events: {
// 'toolClick_Event': 'toolClick_Event'
// }
, render: function () {
var template = _.template($("#layout_temp").html(), {});
$("#Maincontainer").html(template);
//$(this.el).append("<ul> <li>hello world</li> </ul>");
}
});
});
And the other Module that triggers the event using MyApp.vent.trigger.
MyApp.module("OrganizerModule", function (OrganizerModule, MyApp, Backbone, Marionette, $, _) {
// Private Data And Functions
// --------------------------
var myData = "this is private data";
var myFunction = function () {
console.log(myData);
}
// Public Data And Functions
// -------------------------
OrganizerModule.someData = "public data";
OrganizerModule.someFunction = function () {
//console.log(MyModule.someData);
alert(OrganizerModule.someData);
}
OrganizerModule.ExplorerView = Backbone.View.extend({
el: "#center",
events: {
'click button': 'toolClick'
}
, initialize: function () {
this.render();
this.setElement(this.el);
}
, render: function () {
var template = _.template($("#Explorer").html(), {});
//this.$el.html.add(template);
// $("#center").append(template);
//return this.el;
$(this.el).html(template);
return this;
}
, toolClick: function () {
alert("test toolClick");
// var template = _.template($("#Explorer").html(), {});
//$("#center").append(template);
MyApp.vent.trigger('toolClick_Event');
$("#Maincontainer").append("<div> other data </div>");
}
});
});
Hope this will be helpful to others.