Before we start I would like to point out that this is day zero using html / js and knockout so I may just have misunderstood how it all works together.
I have made a simple test webapi so I can get to grips with knockout. It is all working so far but for the binding <span data-bind="text:currentMember().name"></span> which I cannot seem to get to work.
The Page
<!DOCTYPE html>
<html>
<head>
<title>Test page</title>
<script src="Scripts/knockout-2.2.1.js"></script>
<script src="Scripts/jquery-2.0.0.js"></script>
<script src="Scripts/ViewModels/indexViewModel.js" defer="defer"></script>
</head>
<body>
<div id="Content">
<section>
<p>Member Number: </p> <input id="memberNumber" type="text" />
<p>Pin: </p> <input id="memberPin" type="text" />
<input type="submit" value="Get" data-bind="click: getMember" />
</section>
<span data-bind="text:currentMember().name"></span>
</div>
</body>
</html>
The ViewModel
function IndexViewModel() {
var self = this;
self.currentMember = ko.observable();
self.getMember = function () {
var memberNumber = $('#memberId').val();
var memberPin = $('#memberPin').val();
if (memberNumber == '' || memberPin == '') {
memberNumber = '372-001100-134';
memberPin = '123456';
}
$.ajax({
dataType: "json",
url: "http://localhost:25979/api/members/GetMemberByNumberAndPin",
data: {
memberNumber: memberNumber,
pin: memberPin
},
success: function (serviceResponse) {
if (!serviceResponse.hasAlerts) {
self.currentMember(serviceResponse.body);
alert(self.currentMember().name);
}
}
});
};
}
ko.applyBindings(new IndexViewModel());
EDIT: I have changed the code and now the alert does indeed work but the html binding is still not updating.
You have declared currentMember as an observable. And to set the value of an observable, you need to invoke it as a function. So try self.currentMember(serviceResponse.body) instead. If you do self.currentMember = seviceResponse.body as you do, you will essentially re-define the currentMember variable as a regular non-observable variable.
Check the documentation for further explanation.
Related
The 'rightbox' section must show the key and value entered in the form after they were stored using sessionStorage.
I tried Chrome, Firefox, Edge, and Opera browsers. The code didn't work on any of them.
Here is the code:
function doFirst() {
var button = document.getElementById('button');
button.addEventListener('click', saveStuff, false);
}
function saveStuff() {
var one = getElementById('one').value;
var two = getElementById('two').value;
sessionStorage.setItem(one, two);
display(one);
}
function display(one) {
var rightbox = document.getElementById('rightbox');
var thedata = sessionStorage.getItem(one);
rightbox.innerHTML = 'Name of variable: ' + one + '<br />Value: ' + thedata;
}
window.addEventListener('load', doFirst, false);
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<section id="leftbox">
<form>
<p>(key) One: <input type="text" id="one"></p>
<p>(value) Two: <textarea id="two"></textarea></p>
<p><input type="button" id="button" value="Save"></p>
</form>
</section>
<section id="rightbox">
Nothing yet!
</section>
</body>
</html>
The following block from your code:
function saveStuff() {
var one = getElementById('one').value;
var two = getElementById('two').value;
console.log(one, two);
sessionStorage.setItem(one, two);
display(one);
}
You need to use document.getElementById() instead of just getElementById. That will solve your issue.
Furthemore, you have used document.getElementById() properly in your first function, so make sure to check for errors in the browser console next time before posting a question. That will help you in long run.
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
I'm new the JS and I'm having trouble storing and find the value of a form submission. I'm able to create a simple form (as shown below) but I'm not able to find the value of the submission to store for use later.
I thought I was able to access the for value here var number = document.getElementById('fib-form-number'); but I seem to have done something wrong.
I looked at this post here but that has not seemed to work.
I know the fix is going to be easy .. but I just can't figure it out.
Thanks,
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Form/title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="../static/js/jquery.min.js"></script>
<script type="text/javascript" src="../static/js/index.js"></script>
</head>
<body>
<!-- <input id="input" type="submit" value="Submit" onclick="return submitted();"> -->
<!-- Use form to capture numbers on submission -->
<form id="fib-form">
<input type="number" id="fib-form-number" min="1">
<button type="submit">Submit</button>
</form>
</body>
</html>
JS
// Get value of submission
$(document).ready(function() {
var form = document.getElementById('fib-form');
var number = document.getElementById('fib-form-number');
// Now get the value of the submission
form.onsubmit = function () {
var variable = number.value;
console.log(variable)
}
});
You're misspelling variable:
var variable = number.value;
console.log(varaible)
But you could also use jQuery since you're already using it:
$(document).ready(function() {
var form = $('fib-form');
var number = $('fib-form-number');
// Now get the value of the submission
form.onsubmit = function () {
var variable = number.val();
console.log(variable)
}
});
I'm trying to write a sample AngularJS, and SpringMVC project. The spring methods works fine, but I have a problem with declaraton of function in my site controller. My app should return a word from text input, but when I click the button, I've got this error:
[13:23:58.900] "Error: fnPtr is not a function
parser/_functionCall/<#http://localhost:8080/example/resources/js/Angular/angular.js:6542
ngEventDirectives[directiveName]</</</<#http://localhost:8080/example/resources/js/Angular/angular.js:13256
Scope.prototype.$eval#http://localhost:8080/example/resources/js/Angular/angular.js:8218
Scope.prototype.$apply#http://localhost:8080/example/resources/js/Angular/angular.js:8298
ngEventDirectives[directiveName]</</<#http://localhost:8080/example/resources/js/Angular/angular.js:13255
createEventHandler/eventHandler/<#http://localhost:8080/example/resources/js/Angular/angular.js:2095
forEach#http://localhost:8080/example/resources/js/Angular/angular.js:130
createEventHandler/eventHandler#http://localhost:8080/example/resources/js/Angular/angular.js:2094
"
This is my index.html:
<!DOCTYPE html>
<html lang="en" ng-app="Apken">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="resources/js/Angular/angular.js"></script>
<script src="resources/js/controler.js"></script>
</head>
<body ng-controller="theNamer">
<div class="input-append">
<input style="width:358px;" class="span2" type="text" ng-model="myName" required min="1" />
<button class="btn btn-primary" ng-disabled="!myName" ng-click="send()">Click!</button>
</div>
<ul>
<li ng-repeat="name in names">{{name}}</li>
</ul>
</body>
</html>
And controler.js:
function theNamer ($scope,$http){
$scope.myName='aa';
$scope.fetchList=new function()
{
$http.get('ca/list.json').success(function(thList){
$scope.names = thList;
});
}
$scope.send=new function()
{
$http.post('ca/set/3').success(function(){
$scope.fetchList;
});
}
$scope.fetchList;
}
var Apken = angular.module('Apken',[]);
Apken.controller('theNamer', theNamer);
I've noticed, that must be a some kind of problem with function declaration in the ng-click value. On site startup controler.js works fine, but it crashes, when I click the button.
Just wanted to add for anybody receiving this error, it can also be seen if you, like me, make the n00b mistake of creating a variable with the same name as function (the function being called from ng-click:
$scope.addTask = {};
$scope.addTask = function() {};
I have tested your code. Using AngularJS 1.0.7, the error disappears when you replace
$scope.send = new function() {
with
$scope.send = function () {
and same applies to fetchList.
I guess you mixed the two syntaxes function(*args*) { *body* } and new Function(*args*, *body*). Check on MDN: Function.
You have also to change your code in order to get your fetchList properly called:
function theNamer($scope, $http) {
$scope.myName = 'aa';
$scope.fetchList = function() {
$http.get('ca/list.json').success(function(thList) {
$scope.names = thList;
});
};
$scope.send = function() {
$http.post('ca/set/3').success(function() {
$scope.fetchList();
});
};
$scope.fetchList();
}
I'm working on a sample app from the book, AngularJS.
In the following code, {{funding.needed}} doesn't show up as 10 * startingEstimate. It shows up literally, i.e. not rendered, as {{funding.needed}} on the page.
Why?
<html ng-app>
<body ng-controller="TextController">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js">
</script>
<form ng-controller="StartUpController">
Starting: <input ng-change="computeNeeded()"
ng-model="funding.startingEstimate">
Recommendation: {{funding.needed}}
</form>
<script>
function StartUpController($scope) {
$scope.funding = { startingEstimate: 0};
$scope.computeNeeded = function() {
$scope.needed = $scope.startingEstimate * 10;
};
}
</script>
</body>
</html>
You need to remove the TextController as you have not defined this and it's blocking loading other things as it errors. Also you'll need to normalize your use of the $scope.funding object in some places you try to use just the members without the parent reference. The following is a working version (see it working on the plunker at http://plnkr.co/edit/Jz95UlOakKLJIqHvkXlp?p=preview)
<html ng-app>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js">
</script>
<form ng-controller="StartUpController">
Starting: <input ng-change="computeNeeded()"
ng-model="funding.startingEstimate">
Recommendation: {{funding.needed}}
</form>
<script>
function StartUpController($scope) {
$scope.funding = { startingEstimate: 0};
$scope.computeNeeded = function() {
$scope.funding.needed = $scope.funding.startingEstimate * 10;
};
}
</script>
</body>
</html>
I have this knockout code:
function Task(data) {
this.title = ko.observable(data.title);
this.isDone = ko.observable(data.isDone);
}
function TaskListViewModel() {
// Data
var self = this;
self.tasks = ko.observableArray([]);
self.newTaskText = ko.observable();
self.incompleteTasks = ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(), function(task) { return !task.isDone() });
});
// Operations
self.addTask = function() {
self.tasks.push(new Task({ title: this.newTaskText() }));
self.newTaskText("");
};
self.removeTask = function(task) { self.tasks.remove(task) };
}
ko.applyBindings(new TaskListViewModel());
This html:
<head>
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="knockout-2.0.0.js"></script>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<h3>Tasks</h3>
<form data-bind="submit: addTask">
Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
<button type="submit">Add</button>
</form>
<ul data-bind="foreach: tasks, visible: tasks().length > 0">
<li>
<input type="checkbox" data-bind="checked: isDone" />
<input data-bind="value: title, disable: isDone" />
Delete
</li>
</ul>
You have <b data-bind="text: incompleteTasks().length"> </b> incomplete task(s)
<span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span>
</body>
The example is the same as the one found on the Knockout website, but when I run it, it returns this message on Chrome Fire Bug:
Uncaught TypeError: Cannot read property 'nodeType' of null
This one is related to the knockout file and to this line of my script:
ko.applyBindings(new TaskListViewModel());
And this error is pointing to this line (1766) on knockout:
var isElement = (nodeVerified.nodeType == 1);
What am I doing wrong?
This problem was happening because I was trying to bind an HTML element before it was created.
My script was loaded on top of the HTML (in the head) but it needed to be loaded at the bottom of my HTML code (just before the closing body tag).
Thanks for your attention James Allardice.
A possible workaround is using defer="defer"
<script src="script.js" type="text/javascript" defer="defer"></script>
Use this if the script is not going to generate any document content. This will tell the browser that it can wait for the content to be loaded before loading the script.
Further reading.
Hope it helps.
You might want to consider using the jquery ready handler for this
$(function() {
function TaskListViewModel() {
...
ko.applyBindings(new TaskListViewModel());
});
Then you achieve two things:
Avoid polluting the global namespace
Knockout binding occurs AFTER the DOM is created. You can place your javascript wherever it is suited for organization.
See http://api.jquery.com/ready/
if you have jQuery put apply binding inside onload so that knockout looks for the DOM when DOM is ready.
$(document).ready(function(){
ko.applyBindings(new TaskListViewModel());
});
You have a simple spelling mistake:
self.addTask = fuction() {
Should be:
self.addTask = function() { //Notice the added 'n' in 'function'