KO ReferenceError: Unable to process binding - javascript

Uncaught ReferenceError: Unable to process binding "foreach: function (){return Educations }"
Uncaught ReferenceError: Unable to process binding "foreach: function (){return WorkExperience }"
I couldn't figure out why the binding is failing.
i have the following two tables one for Education and other for Work Experience, They give the error when i'm trying to bind the both table in one view, If i remove the binding (JS + HTML code) it works fine
HTML:
<div id=divtable1 class="widget widget-simple widget-table">
<table id="Table1" class="table table-striped table-content table-condensed boo-table table-hover">
<thead>
<tr id="Tr1" class="filter">
<th>University<span class="required">*</span></th>
<th>Location <span class="required">*</span></th>
<th></th>
</tr>
</thead>
<tbody data-bind='foreach: Educations'>
<tr>
<td><input type="text" class='span11 required' data-bind="value: SchoolName" /></td>
<td><input type="text" class='span11 required' data-bind="value: Location" /></td>
<td><a href='#' data-bind='click: $root.removeEducation'>Delete</a></td>
</tr>
</tbody>
</table>
<button data-bind='click: $root.addEducation' class="btn btn-blue">Add Education</button>
</div>
<div id="divtable2">
<table id="Table2">
<thead>
<tr id="Tr2" class="filter">
<th>Employer Name<span class="required">*</span></th>
<th>EmployerAddress <span class="required">*</span></th>
<th></th>
</tr>
</thead>
<tbody data-bind='foreach: WorkExperience'>
<tr>
<td><input type="text" class='span11 required' data-bind="value: EmployerName" /></td>
<td><input type="text" class='span11 required' data-bind="value: EmployerAddress" /></td>
<td><a href='#' data-bind='click: $root.removeWorkExperience'>Delete</a></td>
</tr>
</tbody>
</table>
<button data-bind='click: $root.addWorkExperience' class="btn btn-blue">Add Work Experience</button>
</div>
Java Script:
<script type="text/javascript">
var Educations = function (educations) {
var self = this;
self.Educations = ko.mapping.fromJS(educations);
self.addEducation = function () {
self.Educations.push({"SchoolName": ko.observable(""), "Location": ko.observable("")});
};
self.removeEducation = function (education) {
self.Educations.remove(education);
};
};
var viewModel = new Educations(#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Educations)));
ko.applyBindings(viewModel);
</script>
<script type="text/javascript">
var WorkExperience = function (workexperiences) {
var self = this;
self.WorkExperience = ko.mapping.fromJS(workexperiences);
self.addWorkExperience = function () {
self.WorkExperience.push({ "EmployerName": ko.observable(""), "EmployerAddress": ko.observable("")});
};
self.removeWorkExperience = function (workexperience) {
self.WorkExperience.remove(workexperience);
};
};
var viewModel = new WorkExperience(#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.WorkExperience)));
ko.applyBindings(viewModel);
</script>
Also I tried to bind Table1 but it didn't work
ko.applyBindings(viewModel, $('#Table1')[0]);

try adding this <pre data-bind="text: ko.toJSON($data, null, 2)"></pre> to your view. it will output the data that knockout contains in the current context.
Also you have one view and two view models that are trying to bind to it. create one viewmodel with both Educations and WorkExperience as properties.
something like
var vm = {
Educations : educationViewModel,
WorkExperience: workExperienceViewModel
}
ko.applyBindings(vm);

If you want to bind two view-models separately, you must define which section of your view to bind to. You do this by providing the element to ko.applyBindings as the second parameter.
ko.applyBindings(viewModel, document.getElementById("divtable1"));

Related

The 'click' binding is not working - unable to call the function -- Knockout.js

I have the following in my View:
<div data-bind='foreach: providers'>
<div data-bind='text: name'></div>
<button data-bind='click: model.addToCart'>Show</button>
<table class="table">
<thead>
<th style="width: 300px">Name</th>
<th>Price</th>
<th></th>
</thead>
<tbody data-bind='foreach: items'>
<tr>
<td data-bind='text: name'></td>
<td data-bind='text: price'></td>
<td>
<input type="button" data-bind='click: model.add' value="Add">
</td>
</tr>
</tbody>
</table>
</div>
And the following in my model:
function model() {
var self = this;
self.providers = data; //some random array data
self.addToCart = function(place) {
console.log(place);
}
};
I have used the normal click binding in the Knockout.js.
When I run the code, it seems that the addToCart function is not even being called. I get no output from console.log() for any value.
What have I missed? I'm a beginner. Please help out.
Once inside a foreach loop, your scope is the object you're currently iterating on. So, to refer to a function in the parent or root scope you're gonna have to use $root (although $parent is the same in this case):
<button data-bind='click: $root.addToCart'>Show</button>
See Documentation
your parent View Model should have
var self = this;
self.providers = ko.observableArray();
self.model = new Model();
then in your foreach loop you can use
$root.model.addToCart()

setting viewmodel property to be an item from a list

ok so i have my view model
function viewModel(calendarData) {
var self = this;
self.Calendars = ko.mapping.fromJS(calendarData);
self.ViewedCalendar = {};//what can/should i set this to be on initial creation?
self.DisplayCalendar = function (calendar) {
self.ViewedCalendar = calendar;
};
};
I then have my html:
<div data-bind="visible: Calendars().length > 0">
<h2>You have <span data-bind="text: Calendars().length"></span> calendars</h2>
<table class="table">
<thead>
<tr>
<th>Calendars</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: Calendars">
<tr>
<td data-bind="text: Name"></td>
<td><span data-bind="text: Events().length"></span> events</td>
<td><a href='#' data-bind='click: $root.DisplayCalendar'>View</a></td>
</tr>
</tbody>
</table>
</div>
<div data-bind="visible: ViewedCalendar() !== null">
Your are viewing <span data-bind="text: ViewedCalendar.Name"></span><br />
</div>
What I am trying to achieve is when the user clicks View for a given calendar, that via DisplayCalendar() I set the property ViewedCalendar to be set to the given calendar.
This then shows my div that contains the label stating what calendar is being viewed.
This is all rough code at the minute just to get the basic functionality in place but I'm new to knockout so could use some help.
I'm getting TypeError: ViewedCalendar is not a function or ViewedCalendar is undefined.
Any help would be much appreciated.
The ViewedCalendar property needs to be an observable for knockout to reach to changes in it's value. You defined it like this:
self.ViewedCalendar = {};
Which is an (empty) object literal and not a function (as the error message correctly stated). What you need is:
self.ViewedCalendar = ko.observable(); // empty () give you an empty observable - no calendar selected yet
And then you can update it in your click handler with:
self.ViewedCalendar(calendar);
Here's a working full example:
function viewModel(calendarData) {
var self = this;
self.Calendars = ko.mapping.fromJS(calendarData);
self.ViewedCalendar = ko.observable();
self.DisplayCalendar = function (calendar) {
self.ViewedCalendar(calendar);
};
};
ko.applyBindings(new viewModel([{Name:'some calendar', Events: []}, {Name:'another calendar', Events: []}]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<div data-bind="visible: Calendars().length > 0">
<h2>You have <span data-bind="text: Calendars().length"></span> calendars</h2>
<table class="table">
<thead>
<tr>
<th>Calendars</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: Calendars">
<tr>
<td data-bind="text: Name"></td>
<td><span data-bind="text: Events().length"></span> events</td>
<td><a href='#' data-bind='click: $root.DisplayCalendar'>View</a></td>
</tr>
</tbody>
</table>
</div>
<div data-bind="with: ViewedCalendar">
Your are viewing <span style="font-weight: bold" data-bind="text: Name"></span><br />
</div>

KnockoutJS multiple data-bindings - value and javascript function

I want to have multiple data-bindings on my view so my text box contains the right value and when the value changes it calls a function. Basically I want to use amplify.js local storage every time a value on my form changes.
Agency view
<section class="view">
<header>
<button class="btn btn-info btn-force-refresh pull-right"
data-bind="click: refresh">
<i class="icon-refresh"></i>Refresh</button>
<button class="btn btn-info"
data-bind="click: save">
<i class="icon-save"></i>Save</button>
<h3 class="page-title" data-bind="text: title"></h3>
<div class="article-counter">
<address data-bind="text: agency().length"></address>
<address>found</address>
</div>
</header>
<table>
<thead>
<tr>
<th>Agency Name</th>
<th>Category</th>
<th>URL</th>
<th>Number of employees</th>
</tr>
</thead>
<tbody data-bind="foreach: agency">
<tr>
<td>
<!--<input data-bind="value: agencyName" /></td>-->
<input data-bind="value: agencyName, onchange: test()"/>
<td>
<input data-bind="value: category" /></td>
<td>
<input data-bind="value: Url" /></td>
<td>
<input data-bind="value:numberOfEmployees" /></td>
</tr>
<tr>
<td>Activities</td>
<td>Declared Billings</td>
<td>Campaigned Billings</td>
</tr>
<tr>
<td>
<input data-bind="value: activities" /></td>
<td>
<input data-bind="value: declaredBillings" /></td>
<td>
<input data-bind="value: campaignBillings" /></td>
</tr>
</tbody>
</table>
</section>
Agency ViewModel
define(['services/datacontext'], function (dataContext) {
//var myStoredValue = amplify.store("Agency"),
// myStoredValue2 = amplify.store("storeExample2"),
// myStoredValues = amplify.store();
var agency = ko.observableArray([]);
var initialized = false;
var save = function (agency) {
return dataContext.saveChanges(agency);
};
var vm = { // This is my view model, my functions are bound to it.
//These are wired up to my agency view
activate: activate,
agency: agency,
title: 'agency',
refresh: refresh, // call refresh function which calls get Agencies
save: save
};
return vm;
function activate() {
if (initialized) {
return;
}
initialized = true;
return refresh();
}
function refresh() {
return dataContext.getAgency(agency);
}
function test() {
alert("test");
}
});
Every time I type a new value, for example
<input data-bind="value: agencyName, onchange: test()"/>
I want to fire the function test. I then want to store the view model latest data into local storage.
Does anyone know how to do multiple bindings for this?
You should use this binding:
<input data-bind="value: agencyName, event: { change: $parent.onAgencyNameChanged}"/>
Note that I used $parent to refer to the vm Object.
And add an handler to your viewModel.
var vm = {
....
onAgencyNameChanged: function(agency){
// do stuff
}
};
return vm;
Another solution could be to subscribe on the agencyName of all agencies. But I think this isn't suited to this case. After creating the vm you could do this :
ko.utils.arrayForEach(vm.agency(), function(a){
a.agencyName.subscribe(function(){
// do stuff
});
});
I hope it helps.
Try to subscribe your object manually for each element that you have to bind.
Have a look at the explanation and the example in the knockout documentation here.

knockoutjs table inline template troubles

I slimmed down my actual code but I can't get this work. I am using knockoutjs and bootstrap with inline knockout templates. I use to just put a bunch of input's inside a div but I changed it to a table for alignment reasons. I know the property names are correct and the javascript console doesn't show any errors at all for bad variables or binding issues. I am putting the foreach in a TR tag instead of the TBODY tag because I don't know how many checkboxes I will have every time and I don't want them in rows exactly, just one TR element and a bunch of TD cells inside that one TR tag for now. How can I make this work??
<div id="Counties" class="well well-large checkbox inline">
<table class="table table-condensed">
<tbody>
<tr data-bind="foreach: { data: counties
}">
<td><input type="checkbox" data-bind="attr: { value: $data.sid }" />$data.name
</td>
</tr>
</tbody>
</table>
</div>
Here are my viewModels :
function searchVm() {
var self = this;
self.counties = ko.observableArray([]); //array of jurisItem
}
function jurisItem(name, sid) {
var self = this;
self.name = name;
self.sid = sid;
}
Edit :
I also tried this based on knockoutjs documentation and it doesn't work. I know I can do this in other ways using jquery but I would prefer knockout template syntax...
<table class="table table-condensed">
<tbody>
<tr>
<!-- ko foreach: $root.counties -->
<td>
<input type="checkbox" data-bind="attr: { value: $data.sid }" />$data.name
</td>
<!-- /ko -->
</tr>
</tbody>
</table>
I am not sure what are You trying to do. I made some sample.
html:
<div id="Counties" class="well well-large checkbox inline">
<table class="table table-condensed">
<tbody>
<tr data-bind="foreach: counties">
<td>
<input type="checkbox" data-bind="attr: { value: sid }" />
<span data-bind="text: name" />
</td>
</tr>
</tbody>
</table>
</div>
javascript:
$(function () {
var SearchVm = function () {
var self = this;
self.counties = ko.observableArray([]);
};
var JurisItem = function (name, sid) {
var self = this;
self.name = name;
self.sid = sid;
}
var item1 = new JurisItem("TestName1", "TestSid1");
var item2 = new JurisItem("TestName2", "TestSid2");
var searchViewModel = new SearchVm();
searchViewModel.counties.push(item1);
searchViewModel.counties.push(item2);
ko.applyBindings(searchViewModel);
})
Does this work for You:
http://jsfiddle.net/PVMjy/41/

Knockoutjs Unable to parse bindings. Message: SyntaxError: Unexpected token };

Here is example.
I simplified it as much as i could, but i still can't understand where i'm wrong.
Please help me ))
P.S stackoverflow require a code, not just link to jsfiddle, so this is it:
html:
<form action="" method="GET" data-bind="FacebookContacts">
<table class="importContacts table import">
<thead>
<tr>
<td></td>
<td>Photo</td>
<td>Name</td>
<td>Login</td>
</tr>
</thead>
<tbody data-bind="foreach: contacts">
<tr>
<td>
<span data-bind="text:FullName"></span>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</form>​
javascript:
var FacebookContactsViewModel = function () {
var _self = this;
_self.FacebookContacts = ko.observable();
_self.GetData = function() {
var localData=ko.mapping.fromJS(JSON.parse(contacts));
_self.FacebookContacts(localData);
ko.applyBindings(_self);
};
_self.GetData();
};
var contacts='{"contacts":[{"FullName":"Petr Perelygin"}]}';
var vm = new FacebookContactsViewModel();​
Take a look at here and make your code more simpler and easier to read:
http://jsfiddle.net/NpK3K/24/
The problem was that you are putting an object into the "FacebookContacts" property and not an Array. So you should use the "with" binding extension at the first place for root element to change the datacontext for nested elements.
Hope it helps.

Categories