Simple page not loading KnockoutJS observables - javascript

I'll soon work on some projects that use KnockOutJS, so I'm studying it a bit. I created a simple project containing this simple code (I found it in the official page), but it does not work.
I'm literally doing a copy paste of the official example.
<!DOCTYPE html>
<html>
<head>
<title>KnockOut JS Test</title>
<link href="/Content/bootstrap.css" rel="stylesheet"/>
<link href="/Content/site.css" rel="stylesheet"/>
<script src="/Scripts/modernizr-2.8.3.js"></script>
<script src="/Scripts/jquery-3.3.1.js"></script>
<script src="/Scripts/bootstrap.js"></script>
</head>
<body>
<script type="text/javascript" src="/Scripts/knockout-3.4.2.js">
$(document).ready(function () {
// Here's my data model
var ViewModel = function (first, last) {
this.firstName = ko.observable(first);
this.lastName = ko.observable(last);
this.fullName = ko.computed(function () {
// Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName.
return this.firstName() + " " + this.lastName();
}, this);
};
ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work
}
</script>
<div class='liveExample'>
<p>First name: <input data-bind='value: firstName' /></p>
<p>Last name: <input data-bind='value: lastName' /></p>
<h2>Hello, <span data-bind='text: fullName'> </span>!</h2>
</div>
</body>
</html>
The page should load showing "Hello, Planet Earth", but it only show "Hello, ".

JS library reference tags and actual script tag where you are writing your code should be different. Wrap your js code in <script></script>
<!DOCTYPE html>
<html>
<head>
<title>KnockOut JS Test</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
// Here's my data model
var ViewModel = function (first, last) {
this.firstName = ko.observable(first);
this.lastName = ko.observable(last);
this.fullName = ko.computed(function () {
// Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName.
return this.firstName() + " " + this.lastName();
}, this);
};
ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work
})
</script>
<div class='liveExample'>
<p>First name: <input data-bind='value: firstName' /></p>
<p>Last name: <input data-bind='value: lastName' /></p>
<h2>Hello, <span data-bind='text: fullName'> </span>!</h2>
</div>
</body>
</html>

Related

Form control with angular.js

I have been playing about with angular and forms but I am having some trouble with the code below. I thought that it should add forenames to the ones already displayed by the ng-repeat whenever the form is submitted but the submit button appears to do nothing.
HTML:
<!DOCTYPE html>
<html lang="en" ng-app="file">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
<script types="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script types=text/javascript" src="formLoops.js"></script>
<title>Title</title>
</head>
<body ng-controller="PersonalDetailsController as person">
<p ng-repeat="info in person.details">{{info.forename}}</p>
<form name="PersonalDetailsForm" ng-controller="DataEntryController as dataCtrl" ng-submit="addPerson(person)">
<blockquote>
<p>{{dataCtrl.person.forename}}</p>
<p>{{dataCtrl.person.surname}}</p>
</blockquote>
<label>Forename:</label>
<input ng-model="dataCtrl.person.forename"/>
<label>Surname:</label>
<input ng-model="dataCtrl.person.surname"/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
JS:
var app = angular.module("file", []);
app.controller("PersonalDetailsController", function() {
this.details = personalDetails;
});
app.controller("DataEntryController", function() {
this.person = {};
this.addPerson = function(person) {
person.personalDetails.push(this.person);
};
});
var personalDetails = [{
forename: "John",
surname: "Doe"
},
{
forename: "John",
surname: "Smith"
}
];
You need to do two changes to the code
1) In HTML you need to add the ng-submit="dataCtrl.addPerson(person)"
since you are using the controller as syntax
2) You need to change your js code as follows person.personalDetails.push(this.person); to person.details.push(this.person);
This is because your repeat is working with the details array so you need to push the new data to the details array itself. You are trying to push the data inside the global array that is why it is not worked
Thanks
since you are using the controllerAs use the controllerAs reference when you are calling the function. like ng-submit="dataCtrl.addPerson(person)"
<form name="PersonalDetailsForm" ng-controller="DataEntryController as dataCtrl" ng-submit="dataCtrl.addPerson(person)">
You will need to find a way of sharing data between controllers.
One of the ways is using an angular service.
Check out this plunk!
https://plnkr.co/edit/oimKIgCDKknwsmSWbUsT?p=preview
script.js
var app = angular.module("file", []);
app.controller("PersonalDetailsController", function(PersonService) {
this.details = PersonService.personalDetails;
});
app.controller("DataEntryController", function(PersonService) {
this.person = {};
this.addPerson = function(person) {
PersonService.personalDetails.push(this.person);
};
});
app.service("PersonService", function() {
this.personalDetails = [{
forename: "John",
surname: "Doe"
}, {
forename: "John",
surname: "Smith"
}];
});
index.html
<!DOCTYPE html>
<html lang="en" ng-app="file">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
<script types="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script types="text/javascript " src="script.js"></script>
<title>Title</title>
</head>
<body ng-controller="PersonalDetailsController as person ">
<pre>
{{person | json}}
</pre>
<p ng-repeat="info in person.details ">{{info.forename}}</p>
<form name="PersonalDetailsForm " ng-controller="DataEntryController as dataCtrl " ng-submit="dataCtrl.addPerson(dataCtrl.person) ">
<pre>
{{dataCtrl.person | json}}
</pre>
<label>Forename:</label>
<input ng-model="dataCtrl.person.forename " />
<label>Surname:</label>
<input ng-model="dataCtrl.person.surname " />
<input type="submit " value="submit " />
</form>
</body>
</html>

Javascript/HTML id unidentified

I am trying to use .innerHTML to overwrite a p. The first time i do it, it overwrites it successfully however when i try it a second time it doesn't seem to work. I planned to put in some CSS in the future, so thats is empty. THIS IS THE JAVASCRIPT
function create() {
var x = document.getElementById("cName").value;
var y = document.getElementById("cType").value;
window.alert("Running new card")
newCard(x,y)
}
function newCard(name,type) {
window.alert("new card ran")
this.name = name;
this.type = type;
}
function print(){
document.getElementById("cardName").innerHTML = this.name
document.getElementById("cardType").innerHTML = this.type
}
THIS IS THE HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="main.css" />
<title>TealeStone</title>
</head>
<body>
<script src="JavaScript.js"></script>
<form name="newCard">
Card Name : <input type="text" id="cName" />
Card Type : <input type="text" id="cType" />
<button onclick="javascript:create()">Submit</button>
</form>
<p id="cardName">Card name</p>
<p id="cardType">Card type</p>
<script>
print()
</script>
</body>
</html>

Values wont reflect

This is a very beginner level question as I just started to look at knockout js by downloading js,referring it in my web app.
My simple aspx code. based on first tutorial on knockout js site learning page.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="KnockoutDemo.aspx.cs" Inherits="knockoutjs.KnockoutDemo" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="javascripts/knockout-3.2.0.js" type="text/javascript"></script>
</head>
<body>
<form id="form1" runat="server">
<script type="text/javascript">
function AppViewModel() {
debugger;
this.firstName = "XYZ";
this.lastName = "UU";
}
function callKnockOut() {
debugger;
ko.applyBindings(new AppViewModel());
}
</script>
<div>
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<button id="click" onclick="callKnockOut();"></button>
</div>
</form>
</body>
</html>
ideally the values should take effect after I click button.the code runs through successfully.labels won't show anything!
Knockout is client side javascript library, and you are submitting your form to server so instead of that don't run this at server run it to client i.e. dont write runat="server" for form tag. Then this will absolutely work.
function AppViewModel() {
debugger;
this.firstName = "XYZ";
this.lastName = "UU";
}
function callKnockOut() {
debugger;
ko.applyBindings(new AppViewModel());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<form id="form1" action="#">
<div>
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<button id="click" onclick="callKnockOut();">submit</button>
</div>
</form>

knockout example template example not working

In the following code why does the jquery template not render? I thought that the template was build in? thank you
<script id="friendsTemplate" type="text/html">
<ul>
{{each(index,friend) friends}}
<li>${ friend.name }</li>
{{/each}}
</ul>
</script>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/knockout-2.2.1.js"></script>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>details</h1>
<p>first name: <input data-bind="value: firstName" /></p>
<p>last name: <input data-bind="value: lastName" /></p>
<p>full name: <span data-bind ="text: fullName"></span></p>
<h2>friends</h2>
<div data-bind="template: 'friendsTemplate'"></div>
<script id="friendsTemplate" type="text/html">
<ul>
{{each(index,friend) friends}}
<li>${ friend.name }</li>
{{/each}}
</ul>
</script>
</div>
</form>
</body>
</html>
<script type ="text/javascript">
function friend(name) {
return {
name: ko.observable(name)
};
}
var viewModel ={
firstName: ko.observable("bert"),
lastName: ko.observable("smith"),
friends:ko.observableArray([new friend('steve'),new friend('annie')])
};
viewModel.fullName = ko.dependentObservable(function () {
return this.firstName() + " " + this.lastName();
},viewModel);
ko.applyBindings(viewModel);
</script>
The jQuery.tmpl support is built in however you need to reference jQuery and the jQuery.tmpl to make it work as stated in the documentation under: Note 6: Using jQuery.tmpl, an external string-based template engine:
By default, Knockout comes with support for jquery.tmpl. To use it,
you need to reference the following libraries, in this order:
<!-- First jQuery --> <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<!-- Then jQuery.tmpl --> <script src="jquery.tmpl.js"></script>
<!-- Then Knockout --> <script src="knockout-x.y.z.js"></script>
If you reference all the dependencies your code should work fine: Demo JSFiddle
You need to pass a data object to your template.
data-bind="template: { name: 'friendsTemplate', data: $data }"
Look at http://knockoutjs.com/documentation/template-binding.html for details.
Is there a reason why you are using a jQuery Template? The following is more in alignment with "typical" Knockout usage. Also you should only use external templates if there is reuse. This code could easily be inlined.
<script id="friendsTemplate" type="text/html">
<ul data-bind="friends">
<li data-bind="text: name"></li>
</ul>
</script>

Based on the first knockout tutorial, why is my code not running?

I understand how the tutorial works on the page, but I'm trying to set one up locally to create a calculator and can't get knockout.js to work. It doesn't initialize or populate like the knockout.js online tutorial.
HTML
<html>
<head>
<script type="text/javascript" language="javascript" src="../knockout-2.1.0.js"></script>
<script type="text/JavaScript" language="javascript">
function AppViewModel() {
this.firstName = ko.observable("Bert");
this.lastName = ko.observable("Bertington");
}
// Activates knockout.js
ko.applyBindings(new AppViewModel());
</script>
</head>
<body class="calc" onLoad="createnav()">
<div id="all">
<div id="calc">
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
</div>
<div id="info">
<!-- outputs will be here -->
</div>
</div>
</body>
</html>
I'm using knockout.js version 2.1.0. As for location of the src it is correct.
Folder Structure
----------
| Root |
----------_____________________
| |
------------------- ------------ ---------------
| knockout-2.1.0.js | | pphcalc | ___ | HeroPilot.asp |
------------------- ------------ ---------------
Any suggestions?
If you're not using jquery, don't load it specially for this. Instead you can activate knockout on window.onload. Example:
Wrap your ko.applyBindings call in a function:
function startKnockout() {
ko.applyBindings(new AppViewModel());
};
Pass the name of your "start" function to window.onload. Note, don't add the () to the function name. This prevents the function executing immediately, and instead ensures it is called as a callback function when the window is loaded.
window.onload = startKnockout;
You are applying the bindings in a header script tag so there are not yet any elements to bind to at the point that your ko.applyBindings(new AppViewModel()) line runs.
You can provide a callback for the JQuery Window.load function to ensure that everything is properly loaded before the bindings get applied. Example:
<script type="text/JavaScript" language="javascript">
function AppViewModel() {
this.firstName = ko.observable("Bert");
this.lastName = ko.observable("Bertington");
}
// Activates knockout.js
$(window).load(function() {
ko.applyBindings(new AppViewModel());
});
</script>

Categories

Resources