Trying to get a simple example with firebase and knockoutjs working. All i'm trying to do is take what is in firebase and bind it to my template in knockout. Sounds simple enough right? Well here is the code that's not working. I've looked it over but maybe I'm missing something. Oh this also makes use of knockoutfire.
<!DOCTYPE html>
<html>
<head>
<title>knockout</title>
</head>
<body>
<div id="viewModel">
<ul data-bind="foreach: chat">
<li data-bind="text: nick"></li>
</ul>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script>
<script type="text/javascript" src="knockout.js"></script>
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase.js'></script>
<script type="text/javascript" src='knockoutFire/knockoutFire.js'></script>
<script type="text/javascript" src='model.js'></script>
</body>
</html>
and the model.js:
var firebase = new Firebase("https://kingpinapp.firebaseio.com");
var viewModel = KnockoutFire.observable(firebase, {
chat: {
nick: true,
}
});
ko.applyBindings(viewModel, document.getElementById("viewModel"));
if I'm some how getting the model view wrong checkout the firebaseio link to see how the data is laid out. All I get when I visit index.html is a list with nothing in it. Just a bullet point, nothing else.
EDIT: just realised no one else can see my data. Well here is the JSON downloaded from the url:
{
"chat" : {
"nick" : "hello"
}
}
I think you must use with: chat instead of foreach: chat
<ul data-bind="with: chat">
If you need foreach binding, data in firebase look like;
{
"chat": {
"-XXX": {"nick": "hello"},
"-YYY": {"nick": "hi"}
}
}
and code:
var viewModel = KnockoutFire.observable(firebase, {
chat: {
"$chat": {
nick: true,
}
}
});
Related
I got an error when I want try to add a component into a div DOM in another component.
Uncaught Error: Assertion Failed: You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.
here is my JSBin
App = Ember.Application.create();
App.MyListComponent= Ember.Component.extend({
layoutName:'my-list',
actions:{
addItem:function(){
console.log("add item action");
App.MyListItemComponent.create().appendTo("#holder");
},
},
});
App.MyListItemComponent= Ember.Component.extend({
layoutName:'my-list-item',
});
html, body {
margin: 20px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://builds.emberjs.com/release/ember-template-compiler.js"></script>
<script src="http://builds.emberjs.com/release/ember.debug.js"></script>
</head>
<body>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{my-list}}
</script>
<script type="text/x-handlebars" id="my-list">
<button {{action "addItem"}}>add item</button>
This is a holder:
<div id="holder">
i am inside holder
</div>
This is static item:
{{my-list-item}}
</script>
<script type="text/x-handlebars" id="my-list-item">
i am a list item
</script>
</body>
</html>
can you have a look and tell me how to do?
thank you very much
I dont think, your approach is right.
A component should be working independently from the context in which it is added. You can pass anything as argument to the component within the template. I would recommend displaying the components depending on some type of model that is added with each addItem click (in my example, a simple text).
Why don't you try it this way:
JS
App = Ember.Application.create();
App.MyListComponent= Ember.Component.extend({
components: Ember.A([]),
layoutName:'my-list',
actions:{
addItem:function(){
var components = this.get('components');
console.log(components);
components.pushObject ('test'); // or whatever you want: could also be components.pushObject(App.MyListItemComponent.create()); if you want to use it later somehow.
this.set('components', components);
console.log("add item action");
},
},
});
App.MyListItemComponent= Ember.Component.extend({
layoutName:'my-list-item',
});
html
<script type="text/x-handlebars" id="my-list">
<button {{action "addItem"}}>add item</button>
This is a holder:
<div id="holder">
i am inside holder {{components.length}}
{{#each components as |item|}}
{{my-list-item}}
{{/each}}
</div>
This is static item:
{{my-list-item}}
What am I doing wrong? angular.min.js is in the folder js. I am using the book from O'Reilly. There is an example like this. But on my PC it doesn't work.
//controller.js
function HelloController($scope) {
$scope.greeting = { text: 'Hello' };
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/controller.js"></script>
</head>
<body ng-app="">
<div ng-controller='HelloController'>
<p>{{greeting.text}}, World</p>
</div>
</body>
</html>
I think you are referring to old book. Please update your controller as below
//controller.js
var app = angular.module('myApp', []);
app.controller('HelloController', function($scope) {
$scope.greeting = { text: 'Hello' };
});
and in HTML
ng-app="myApp"
Please try and let us know whether it is working or not
I am brand new to marionette and am following along with a textbook to build a simple app using marionette. I ran into this problem almost immediately, they telly you to put a console.log() in a function, except it doesn't show up in my browser when i run it. Here's the script below:
<script type="text/javascript">
var ContactManager = new Marionette.Application();
ContactManager.on("initialize:after", function(){
console.log("ContactManager has started!");
});
ContactManager.start();
</script>
And here's the whole HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Marionette Contact Manager</title>
<link href="./assets/css/bootstrap.css" rel="stylesheet">
<link href="./assets/css/application.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<span class="brand">Contact manager</span>
</div>
</div>
</div>
<div class="container">
<p>Here is static content in the web page. You'll notice that it gets 21 replaced by our app as soon as we start it.</p>
</div>
<script src="./assets/js/vendor/jquery.js"></script>
<script src="./assets/js/vendor/json2.js"></script>
<script src="./assets/js/vendor/underscore.js"></script>
<script src="./assets/js/vendor/backbone.js"></script>
<script src="./assets/js/vendor/backbone.marionette.js"></script>
<script type="text/javascript">
var ContactManager = new Marionette.Application();
ContactManager.on("initialize:after", function(){
console.log("ContactManager has started!");
});
ContactManager.start();
</script>
</body>
</html>
Any help would be greatly appreciated, I can do a console.log() outside of the ContactManager.on() code and it will work. Any ideas?
So i figured out the answer to my own question with a little research. Marionette has updated "initialize:after" to "start". For a full list of updates you can check here -->
https://github.com/marionettejs/backbone.marionette/blob/master/changelog.md#v100-rc1-view-commit-logs
How can i move the javascript code that's using knockout outside the html file? I want to create a separate file where everything is handled (or as much as possible). Also the templating should still work. Thanks in advance!
EDIT: Changes made. I have added the require.js in my Scripts folder and made an app.js and viewmodel.js file. But this still won't work. Any help would be very much appreciated :)
EDIT2: Almost there, Rumesh Eranga gave the right answer with using require.js. I only have a little problem left with my binding. 'data-bind="text: $(item.name)"' won't show the name, only '[object Object]'.
EDIT3: SOLVED!
This is the HTML file:
<head>
<script type="text/javascript" data-main="Script/app.js" src="Scripts/require.js"></script>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="Scripts/jquery.tmpl.js"></script>
<script id="shoppingItemTemplate" type="text/html">
<li><span data-bind="text: item.name"></span></li>
</script>
<div id="ActiveShoppingList">
<h2>Shopping items</h2>
<div id="ActiveList">
<ul data-bind="template: {name:'shoppingItemTemplate', foreach: items, as:'item'}"></ul>
<button data-bind="click:addItem">Add item</button>
</div>
</div>
</body>
Here is my Script/app.js:
require(['knockout-3.2.0', 'viewmodel'], function(ko, viewmodel) {
ko.applyBindings(new viewmodel);
});
And here is my Script/viewmodel.js:
define(['knockout-3.2.0'], function(ko) {
return function viewmodel (){
this.items = ko.observableArray([new item("item1"), new item("item2")]);
this.addItem = function()
{
this.items.push(new item("new item"));
};
};
function item(name)
{
return { name: ko.observable(name) };
}
});
Use Asynchronous Module Definition (AMD) With RequireJs.
Good article on Require and knockout can be found here.
Quoting from the site.
HTML
<html>
<head>
<script type="text/javascript" data-main="scripts/init.js" src="scripts/require.js"></script>
</head>
<body>
<p>First name: <input data-bind="value: firstName" /></p>
<p>First name capitalized: <strong data-bind="text: firstNameCaps"></strong></p>
</body>
</html>
scope/init.js
require(['knockout-x.y.z', 'appViewModel', 'domReady!'], function(ko, appViewModel) {
ko.applyBindings(new appViewModel());
});
scripts/appViewModel.js
// Main viewmodel class
define(['knockout-x.y.z'], function(ko) {
return function appViewModel() {
this.firstName = ko.observable('Bert');
this.firstNameCaps = ko.pureComputed(function() {
return this.firstName().toUpperCase();
}, this);
};
});
According to the code snippet given above you can see that you can make your view model code separate from the html and even can be modularize which is much helpful.
here is my django rendered test page
<!doctype html>
<html lang="en">
<head>
</head>
<body>
<div id="todo">
</div>
<script type="text/template" id="item-template">
<div>
<input id="todo_complete" type="checkbox" <%= completed ? 'checked="checked"' : '' %>>
<%- title %>
</div>
</script>
<script src="jquery.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>
<script src="app.js"></script>
//the app.js is my backbone app
<script >
var foo_models = new fooCollection({{django_rendered_json_vaiable}})
//this is how I get backbone collection initial data
</script>
</body>
</html>
the above code is what I get so far, I get the backbone bootstrapped models as foo_models,
but this variable can't be access in my app.js file, then I found this question, which use AMD approach,but my app is fairly small,all I need is get the initial data in another js file,so I don't want to add require.js and I don't want to make this foo_models variable global。
so how can I do that?
* EDITED *
Just change these lines:
<script src="app.js"></script>
//the app.js is my backbone app
<script >
var foo_models = new fooCollection({{django_rendered_json_vaiable}})
//this is how I get backbone collection initial data
</script>
to:
<script >
var raw_foo_models = {{django_rendered_json_vaiable}};
</script>
<script src="app.js"></script>
Then, add this line:
var foo_models = new fooCollection(raw_foo_models);
somewhere in your app (after fooCollection has been defined).