How do I access my viewmodel variables in my knockout component template? - javascript

I am trying to create a list of instruction steps using Knockout components/templates.
The UL is the going to contain a list of steps (using a knockout-registered custom element sidebar-step) which is just a template of <li></li>. I have another value this.testVar part of my model that could contain an attribute of <li> such as the class, or maybe a "data-customAttribute".
My question is, how do I include my testVar value into the template? I want it so that it might output a line like:
<sidebar-step class=*testVar* params="vm: sidebarStepModel">Message 1</sidebar-step>
Fiddle: https://jsfiddle.net/uu4hzc41/1/
HTML:
<ul>
<sidebar-step params="vm: sidebarStepModel"></sidebar-step>
</ul>
JavaScript:
ko.components.register("sidebar-step", {
viewModel: function (params) {
this.vm = params.vm;
},
template: "<li data-bind=\'text: vm.message\'></li>"
});
var SidebarStepModel = function () {
this.message = ko.observable("step description");
this.testVar = ko.observable("some value");
};
var ViewModel = function () {
this.sidebarStepModel = new SidebarStepModel();
this.sidebarStepModel.message("Message 1");
this.sidebarStepModel.testVar("69");
};
ko.applyBindings(new ViewModel());

You can use data-bind on the custom tag. To set class,
<sidebar-step data-bind="css:sidebarStepModel.testVar" params="vm: sidebarStepModel"></sidebar-step>
https://jsfiddle.net/uu4hzc41/3/

Related

pass ViewBag to js function

I am having a dropdown list in which I call a js function, on change event.
In View:
#Html.DropDownList("RaceId", ViewData["Races"] as List<SelectListItem>, new { #onchange = "CallChangefunc(this.value)", #class="form-control" })
and my js:
<script>
function CallChangefunc(val)
{
//called in Index page when dropdown list changes
window.location.href = "/Index/" + val;
}
</script>
What I want is to add a new argument to my js function where I pass a ViewBag value, sth like:
#Html.DropDownList("RaceId", ViewData["Races"] as List<SelectListItem>, new { #onchange = "CallChangefunc(this.value,ViewBag.id)", #class="form-control" })
The above does not work and I am not sure which is the correct syntax, if any.
First, use unobtrusive javascript instead of onchange attribute. If you have your javascript inside your view, you can access ViewBag too, using '#ViewBag':
$('#RaceId').on('change', function()
{
var value = $(this).val();
var id = '#ViewBag.id'
}
);
Or if you're running your javascript on a different file, you can use a Hidden input and get this value in your script:
#Html.Hidden("Id", ViewBag.id)
and in you script:
$('#RaceId').on('change', function()
{
var value = $(this).val();
var id = $("Id").val();
}
);
Although Stephen's comment is 100% correct, i would just like to know if this solves your problem:
#{
var htmlAttr = new Dictionary<string, object>();
htmlAttr.Add("onchange", string.Format("{0}{1})", "CallChangefunc(this.value", #ViewBag.id));
htmlAttr.Add("class", "form-control");
}
#Html.DropDownList("RaceId", ViewData["Races"] as List<SelectListItem>, #htmlAttr)

How to bind a Kendo UI list to a ViewModel?

I have this fallowing list:
<ul data-template="view" data-bind="source: contacts"></ul>
...
<script type="text/x-kendo-template" id="view">
<li>
<div data-role="button" data-bind="click: viewContact">
<h4>#: first_name #</h4>
</div>
</li>
</script>
var someClass = kendo.observable({
title : 'Contact',
contacts : [],
getContacts: function () {
var data = new Contacts().get();
$.when(data()).then(function (data) {
someClass.contacts = data;
});
}
});
I want to assign data from getContacts to products and populate the template with results as they come in.
Any ideas?
In your question you are talking about "products" but in the code snippet i see "contacts".
In any case, you need to do the following:
someClass.set('contacts', data)
Note: assuming you have contacts as a property on the viewmodel.
Since its an observable object, if you don't use get() & set() methods, kendo wont know who all are observing that property. If you use set() method to set new value, Kendo will propagate the change and will notify the listeners of the property.

Knockout foreach binding, update value

I got ko model:
var Model = function(notes) {
this.note = ko.observableArray(notes);
};
var model = new Model([{"post":"a"},{"post":"b"}]);
ko.applyBindings(model);
And html div:
<div data-bind='foreach: note'>
<p><span data-bind='text: post'>
<p><input data-bind='value: post'>
</div>
Here's fiddle: http://jsfiddle.net/DE9bE/
I want to change my span value when new text is typed in input, like in that fiddle: http://jsfiddle.net/paulprogrammer/vwhqU/2/
But it didnt updates. How can i do that in foreach bindings?
The properties of the objects need to be made into observables.
You could do this yourself manually (i've used the plain js array map method here, if you need IE8 support you can use ko.utils.arrayMap for the same purpose):
var Model = function(notes) {
this.note = ko.observableArray(notes.map(function(note){
note.post = ko.observable(note.post);
return note;
}));
};
var model = new Model([{"post":"a"},{"post":"b"}]);
ko.applyBindings(model);
Demo
Or you can use the mapping plugin (seperate js file that you need to include) which does this (recursively) for you.
var Model = function(notes) {
this.note = ko.mapping.fromJS(notes);
};
var model = new Model([{"post":"a"},{"post":"b"}]);
ko.applyBindings(model);
Demo
If you get the whole data object from the server you could also feed it directly:
var model = ko.mapping.fromJS({
note: [{"post":"a"},{"post":"b"}]
});
ko.applyBindings(model);
Demo
What you want is an observable array with observables, or else your span will not be updated since you are changing a non-observable variable, see this post.
KnockoutJS - Observable Array of Observable objects
Try this:
HTML
<div data-bind='foreach: note'>
<p><span data-bind='text: post'></span></p>
<p><input data-bind='value: post'/></p>
</div>
JavaScript
var Model = function (notes) {
this.note = ko.observableArray(notes);
};
var Post = function (data) {
this.post = ko.observable(data);
};
var model = new Model([new Post("a"), new Post("a")]);
ko.applyBindings(model);
Demo

Calling variable in template from view of backbone

I'm using text! plug-in of require.js to load javascript templates of my backbone project.
Here it is :
<table id="showcart">
<tr><td class="cartitemhead">Item to buy</td><td class="cartitemhead" style="text-align: center;">Quantity</td></tr>
<% _.each(item, function(item) { %>
<tr><td><table class="verticallist"><tr><td rowspan="4" style="width: 120px;"><img src="<%=item.PictureName%>" alt="Product" width="95px"/></td><td style="font-weight: bold;"><%=trimString(item.Name,50)%></td></tr><tr><td><i>Available in Stock(s)!</i></td></tr><tr><td><i>Rating: 650Va-390w Input: Single</i></td></tr></table></td><td class="centertxt"><%=item.QuantityInCart%></td></tr>
<% }); %>
</table>
item variable was declared in my view.
var CartListView = Backbone.View.extend({
render: function(){
var item = deserializeJSONToObj(window.localStorage.getItem("Cart"));
var cartList = _.template(showCartTemplate, {})
$("#cartlist").html(cartList);
}
});
Model :
define(["underscore" , "backbone"],function(_ , Backbone){
var Cart = Backbone.Model.extend({
});
});
I got one error from console : Uncaught ReferenceError: item is not defined.
Any help would be much appreciated, thank you.
You need to indicate somehow the value you want to pass for backbone template. Because you have defined a variable, Underscore template is looking for a value to get replaced with.
For this reason try to pass the model value as an argument to the appended view.
var CartListView = Backbone.View.extend({
render: function(){
var item = deserializeJSONToObj(window.localStorage.getItem("Cart"));
var cartList = _.template(showCartTemplate, {})
$("#cartlist").append({item : cartList});
}
});
This way, each time when undercore find a variable item it will replace with the value passed as argument to the view.
You need to pass the item key in the object that you pass in _.template
var CartListView = Backbone.View.extend({
render: function(){
var item = deserializeJSONToObj(window.localStorage.getItem("Cart"));
var cartList = _.template(showCartTemplate, {item : item})
$("#cartlist").append({item : cartList});
}
});
Because you can not access the item variable directly in template.

Multiple Select List and KnockoutJS

I have a multi-select list that I've implemented following the instructions on the KO site. The important portions of my code currently look like this (removed unnecessary code):
function Attribute(data) {
var self = this;
self.Id = data.Id;
self.Name = data.Name;
}
// Individual Row in Table
function Criteria(data) {
var self = this;
self.Attributes = data.Attributes;
}
// Represent the ViewModel for attributes.
function CriteriaViewModel() {
var self = this;
// Catalog Data
self.availableAttributes = window.ko.observableArray([]);
$.getJSON(window.attributeListUrl, function(availableData) {
self.availableAttributes($.map(availableData.Attributes, function(item) { return new Attribute(item); }));
});
// Editable Data
self.criterion = window.ko.observableArray([]);
// Load initial state from server
$.getJSON(window.criteriaListUrl, function (availableData) {
self.criterion($.map(availableData.Criterion, function (item) { return new Criteria(item); }));
});
}
Then, in my HTML, I bind it all together (or, I at least try to):
<tbody data-bind="foreach: criterion">
<tr>
<td>
<select class="selectedAttributes"
data-bind="options: $root.availableAttributes, selectedOptions: Attributes, optionsText: 'Name', optionsValue: 'Id'"
multiple
size="6">
</select>
</td>
</tr>
</tbody>
The possible options display correctly. However, there is no apparent binding between the criteria's attributes against the possible options. From reading the guide, it seems as though KO should be able to bind objects directly. Can anybody provide guidance here?
I forgot to mention that everything works except the actual binding of the multi-select list. I am applying my bindings appropriately in general - just not with the multi-select list.
The attributes property on the Criteria object needs to be an observableArray. Here is a Jsfiddle demonstrating
function Criteria(data) {
var self = this;
self.Attributes = ko.observableArray(data.Attributes);
}
var x= $('#select1 option:selected');
if(x.length>0){
x.each(function(){
alert($(this).text());
self.selectedCategory.push(new categoryModel($(this).text()));
$('#select1 option:selected').remove();
});
}
refer http://jsfiddle.net/deepakpandey1234/wse4gdLq/

Categories