KnockoutJS: Making sure items are removing before adding new ones - javascript

I'm running into an issue where ever so often my data isn't being updated properly in my model. I've create a fiddle for it here: https://jsfiddle.net/wzhv5ghy/
In the code all the updates to the model are handled by this function:
self.updateData = function (data) {
self.deliveryItems.removeAll(); // Sometimes our data won't replace correctly so lets kill everything here and then add it from scratch
if ( data != null )
self.deliveryItems(data);
self.showLoadingNotice(false);
// let the sorting plugin know that we made a update
$("#deliveryItemsTable").trigger("update");
//self.showTable(true);
//console.log(data);
// We moved this to functions.js since we use it multiple times
//setupDeliveryItemsTable();
};
I put it in a single function to make it easier when updating the code using various JSON calls.
The issue thats happening is that every so often the page will show old data (say 1000 lines) in the table while the following code will display 1 as the count of the models data:
<span data-bind="text: deliveryItems().length"></span>
My guess is that this line:
self.deliveryItems.removeAll();
is not running before this line
self.deliveryItems(data);
How can I make sure that all items are removed from the model and table before the model is updated with the fresh data?

Like #f_martinez pointed out our issue was with the jQuery Tablesorter plugin and KO fighting to update the same table. To get around this I ended up using the code below to switch to a KO tablesorting function. The sorting seems to be slower than the Tablesorter version but it's better than having bad data.
/*-------------------------------------------------------------------------*/
// Knockout.js Functions
/*-------------------------------------------------------------------------*/
ko.bindingHandlers.sort = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var asc = false;
element.style.cursor = 'pointer';
//console.log(element);
element.onclick = function(){
var value = valueAccessor();
var prop = value.prop;
var data = value.arr;
asc = !asc;
data.sort(function(left, right){
var rec1 = left;
var rec2 = right;
if(!asc) {
rec1 = right;
rec2 = left;
}
var props = prop.split('.');
for(var i in props){
var propName = props[i];
var parenIndex = propName.indexOf('()');
if(parenIndex > 0){
propName = propName.substring(0, parenIndex);
rec1 = rec1[propName]();
rec2 = rec2[propName]();
} else {
rec1 = rec1[propName];
rec2 = rec2[propName];
}
}
return rec1 == rec2 ? 0 : rec1 < rec2 ? -1 : 1;
});
};
}
};
Here's the code for the table itself:
<div class="alert alert-info" data-bind="visible: showLoadingNotice">
Loading...
</div>
<table class="table table-striped table-bordered table-hover" id="deliveryItemsTable" data-bind="visible: showTable">
<thead>
<tr class="title1">
<td colspan="100%">Delivery Items ( <span data-bind="text: deliveryItems().length"></span> )</td>
</tr>
<tr class="title2">
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'created_on' }">Created On</th>
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'company_name' }">Company</th>
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'product_number_company' }">Item Number</th>
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'client_phone_number' }">Phone Number</th>
<th data-bind="sort: { arr: deliveryItems, prop: 'price_to_display' }">Price</th>
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'location' }">Location</th>
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'notes' }">Notes</th>
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'delivered_by_text' }">Delivery Driver</th>
<th class="header" data-bind="sort: { arr: deliveryItems, prop: 'status_labels' }">Status</th>
<th class="header nowrap"></th>
</tr>
</thead>
<tbody data-bind="foreach: deliveryItems">
<tr data-bind="attr: {id: 'row_' + id }">
<td data-bind="text: created_on"></td>
<td data-bind="text: company_name"></td>
<td data-bind="text: product_number_company"></td>
<td data-bind="text: client_phone_number"></td>
<td data-bind="text: formatCurrency(price_to_display)"></td>
<td>
<span data-bind="text: location, attr: {id: 'edit-delivery_items-' + id + '_location' }"></span>
<button data-bind="click: $root.editLocation, visible: $root.canEdit" class="btn btn-default btn-xs" title="Edit"><i class="glyphicon glyphicon-edit"></i></button>
</td>
<td>
<span data-bind="text: notes, attr: {id: 'edit-delivery_items-' + id + '_notes' }"></span>
<button data-bind="click: $root.editNotes, visible: $root.canEdit" class="btn btn-default btn-xs" title="Edit"><i class="glyphicon glyphicon-edit"></i></button>
</td>
<td>
<span data-bind="text: delivered_by_text, attr: {id: 'edit_select-delivery_items-' + id + '_delivered_by' }"></span>
<button data-bind="click: $root.editDeliveryDriver, visible: $root.canEdit" class="btn btn-default btn-xs" title="Edit"><i class="glyphicon glyphicon-edit"></i></button>
</td>
<td data-bind="html: status_labels"></td>
<td class="center"><span class="btn-group">
<button data-bind="click: $root.markAsDelivered, visible: $root.canMarkComplete" class="btn btn-default" title="Mark as delivered"><i class="glyphicon glyphicon-check"></i></button>
<a data-bind="attr: {href: 'index.php?action=editDeliveryItem&id=' + id }, visible: $root.canEdit" class="btn btn-default" title="Edit"><i class="glyphicon glyphicon-edit"></i></a>
</span></td>
</tr>
</tbody>
</table>
<div class="alert alert-info" data-bind="visible: showLoadingNotice">
Loading...
</div>
<div id="deliveryItemsTableUpdateNotice"></div>

Related

How to bind JSON object with knockout on Dropdown change with html table

When I change the dropdown value, json data is change but not loads, and throws this error:
Uncaught Error: You cannot apply bindings multiple times to the same element.
How to resolve this?
$("#VehicleID").change(function () {
var categoryid = $("#VehicleTypeID option:Selected").val().trim();
var subcategoryid = $(this).val();
var url = "../Consignment/LoadratebydetailId";
$.getJSON(url, { CategoryID: categoryid, SubCategory: subcategoryid },
function (classesData) {
//var koNode = document.getElementById('fareDetailbody');
ko.cleanNode(classesData);
//ko.cleanNode($element[0]);
ko.applyBindings({
teams: classesData,
});
});
$("#rateChargeDiv").hide();
$("#rateChargeDiv").show();
});
<div id="rateDiv">
<div>
<h4>Selected Detail Changed</h4>
<table>
<thead>
<tr>
<th>name</th>
<th>cloth</th>
<th>color</th>
<th>size</th>
<th>length</th>
<th>total</th>
</tr>
</thead>
<tbody id="fareDetailbody" data-bind="foreach: teams">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: cloth"></td>
<td data-bind="text: color"></td>
<td data-bind="text: size"></td>
<td data-bind="text: length"></td>
<td data-bind="text: total"></td>
</tr>
</tbody>
</table>
</div>
<div id="close">close</div></div>
public JsonResult LoadratebydetailId(string CategoryID, string SubCategory)
{
if (CategoryID == "" || string.IsNullOrEmpty(CategoryID))
{
return Json("failure");
}
var vehCategory = this.GetratebydetailId(Convert.ToInt32(CategoryID));
var StatesData = vehCategory.
Where(cat => cat.VehicleCategoryID==Convert.ToInt32(SubCategory))
.Select(m => new
{
m.name,
m.cloth,
m.color,
m.size,
m.length,
m.total
});
return Json(StatesData, JsonRequestBehavior.AllowGet);
}

Get data-bind value of button in html table

How get data-bind value in ViewsModel from Button in html table when click ?
Please help me?
Views:
<table border="1">
<thead>
<tr>
<th>
Id
</th>
<th>
Naziv
</th>
</tr>
</thead>
<tbody data-bind="foreach: customers">
<tr>
<td data-bind="text: Id_dobavljaca">
</td>
<td data-bind="text: NazivDobavljaca">
</td>
<td>
<button data-bind="click: edit, value: Id_dobavljaca">
Edit</button>
<button >
Test</button>
</td>
</tr>
</tbody>
</table>
ViewModel:
define(function (require) {
var app = require('durandal/app'), system = require('durandal/system'),
ko = require('knockout');
return {
customers: ko.observableArray([]),
activate: prikazi
}
});
function prikazi() {
var system = require('durandal/system');
var that = this;
system.log('krenu po podatke');
$.ajax({
type: 'GET',
url: '/Durandal/VratiDobavljace',
dataType: "json",
success: function (data) {
that.customers(data);
},
error: function (jq, st, error) {
alert(error);
}
});
system.log('doneo podatke');
edit = function edit1(Id_dobavljaca) {
var system = require('durandal/system');
alert(Id_dobavljaca);
var router = require('plugins/router');
router.navigate('treci/' + 123456);
};
return that.customers
}
I want to pass value ( Id_dobavljaca )in ViewsModels when click button in html table..
Thanks alot!
Martin
In DurandalJS, the object that you return from your requirejs module that is your view model is the object bound to the view. The activate function will be called when DurandalJS composes your view and view model, you can read more here.
In your current implementation the observableArray customers is a property on your view model and can be bound to your view, which is great and I assume working.
However, from looking at your current implementation you have not exposed the edit function on your view model which means it cannot be bound to the UI and used.
I have refactored your view model:
define(function(require) {
var app = require('durandal/app'),
system = require('durandal/system'),
router = require('plugins/router'),
ko = require('knockout');
var customers = ko.observableArray([]);
return {
customers: customers,
edit: function(context) {
alert(context.Id_dobavljaca);
router.navigate('treci/' + context.Id_dobavljaca);
},
activate: function() {
system.log('krenu po podatke');
return $.ajax({
type: 'GET',
url: '/Durandal/VratiDobavljace',
dataType: "json"
})
.done(function(data) { customers(data); })
.fail(function(jq, st, error) { alert(error); })
.always(function() { system.log('doneo podatke'); });
}
}
});
This refactoring exposes the customers observableArray property and the edit function. The activate function also loads your data and returns the promise back to the DurandalJS composition life cycle.
Now, you will notice that the edit function takes an argument called context, this is a knockoutjs thing. When a function is bound to the click binding the first argument passed to the function is the binding context, you can read more here.
Using this refactored view model, in your markup you want to bind your edit button to the edit function on the $root context, which is your view model.
<td>
<button data-bind="click: $root.edit">Edit</button>
<button>Test</button>
</td>
Hopefully, the snippet below can demonstrate this explanation.
var example1 = {
customers: ko.observableArray([{
Id_dobavljaca: 123,
NazivDobavljaca: 'Martin',
edit: function(context) {
alert('Id_dobavljaca: ' + this.Id_dobavljaca);
alert('Id_dobavljaca: ' + context.Id_dobavljaca);
}
}, {
Id_dobavljaca: 321,
NazivDobavljaca: 'Anish',
edit: function(context) {
alert('Id_dobavljaca: ' + this.Id_dobavljaca);
alert('Id_dobavljaca: ' + context.Id_dobavljaca);
}
}, ])
}
ko.applyBindings(example1, $('#example1')[0]);
var example2 = {
customers: ko.observableArray([{
Id_dobavljaca: 123,
NazivDobavljaca: 'Martin'
}, {
Id_dobavljaca: 321,
NazivDobavljaca: 'Anish'
}, ]),
edit: function(context) {
alert('Id_dobavljaca: ' + context.Id_dobavljaca);
}
}
ko.applyBindings(example2, $('#example2')[0]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<p>Edit function is a property on each customer object<p>
<table id="example1" border="1">
<thead>
<tr>
<th>
Id
</th>
<th>
Naziv
</th>
</tr>
</thead>
<tbody data-bind="foreach: customers">
<tr>
<td data-bind="text: Id_dobavljaca">
</td>
<td data-bind="text: NazivDobavljaca">
</td>
<td>
<button data-bind="click: edit">
Edit</button>
<button>
Test</button>
</td>
</tr>
</tbody>
</table>
<br>
<br>
<br>
<p>Edit function is a property on the view model<p>
<table id="example2" border="1">
<thead>
<tr>
<th>
Id
</th>
<th>
Naziv
</th>
</tr>
</thead>
<tbody data-bind="foreach: customers">
<tr>
<td data-bind="text: Id_dobavljaca">
</td>
<td data-bind="text: NazivDobavljaca">
</td>
<td>
<button data-bind="click: $root.edit">
Edit</button>
<button>
Test</button>
</td>
</tr>
</tbody>
</table>
I hope this helps.

How to edit contents in Angular js Smart Table

I am quite new to java script, so I must apologise if this seems basic.
How can I edit rows tables in Smart-Table with Angularjs? There doesn't seem to be a tutorial with the new Smart-Table. I would like to create a simple form for users to enter the hours open for a particular place.
I have created buttons which can add and remove rows on the table, but when I add in contenteditable="true" none of the changes are persisted when I update the object. I understand that the contenteditable is a specific html5 parameters independent of smart-table, but I don't understand how else I can update the data or how I could retrieve the updated data.
The data is retrieved from the angularjs controller via the mean.js routes.
<div class="controls">
<table st-table="place.openHours" class="table table-striped">
<thead>
<tr>
<th>Day</th>
<th>Opening Time</th>
<th>Closing Time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in place.openHours" contenteditable="true" >
<td>{{row.day}}</td>
<td>{{row.open}}</td>
<td>{{row.close}}</td>
<button type="button" ng-click="removeOpenHour(row)" class="btn btn-sm btn-danger">
<i class="glyphicon glyphicon-remove-circle">
</i>
</button>
</tr>
</tbody>
</table>
<button type="button" ng-click="addOpenHour(row)" class="btn btn-sm btn-success">
<i class="glyphicon glyphicon-plus">
</i> Add new Row
</button>
</div>
Inside the javascript:
$scope.removeOpenHour = function removeOpenHour(row) {
var index = $scope.place.openHours.indexOf(row);
if (index !== -1) {
$scope.rowCollection.splice(index, 1);
}
}
$scope.addOpenHour = function addOpenHour() {
$scope.place.openHours.push(
{
day: 'Monday',
open: 540,
close: 1080
});
};
Thanks I had a look around and used the code from here http://jsfiddle.net/bonamico/cAHz7/ and merged it with my code.
HTML file:
<tr ng-repeat="row in place.openHours">
<td><div contentEditable="true" ng-model="row.day">{{row.day}}</div></td>
<td><div contentEditable="true" ng-model="row.open">{{row.open}}</div></td>
<td><div contentEditable="true" ng-model="row.close">{{row.close}}</div></td>
<td>
<button type="button" ng-click="removeOpenHour(row)" class="btn btn-sm btn-danger">
<i class="glyphicon glyphicon-remove-circle">
</i>
</button>
</td>
JS file:
myApp.directive('contenteditable', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.bind('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(elm.html());
});
});
// model -> view
ctrl.render = function(value) {
elm.html(value);
};
elm.bind('keydown', function(event) {
console.log("keydown " + event.which);
var esc = event.which == 27,
el = event.target;
if (esc) {
console.log("esc");
ctrl.$setViewValue(elm.html());
el.blur();
event.preventDefault();
}
});
}
};
});
My solution is it:
Angular directive :
app.directive("markdown", function() {
return {
restrict: 'EA',
scope: {
value: '='},
template: '<span ng-click="edit()" ng-bind="value"></span><input ng-blur="blur()" ng-model="value"></input>',
link: function($scope, element, attrs) {
// Let's get a reference to the input element, as we'll want to reference it.
var inputElement = angular.element(element.children()[1]);
// This directive should have a set class so we can style it.
element.addClass('edit-in-place');
// Initially, we're not editing.
$scope.editing = false;
// ng-click handler to activate edit-in-place
$scope.edit = function() {
$scope.editing = true;
// We control display through a class on the directive itself. See the CSS.
element.addClass('active');
// And we must focus the element.
// `angular.element()` provides a chainable array, like jQuery so to access a native DOM function,
// we have to reference the first element in the array.
inputElement[0].focus();
};
// When we leave the input, we're done editing.
$scope.blur = function() {
$scope.editing = false;
element.removeClass('active');
}
}
};
});
HTML:
<table st-table="displayedCollection" st-safe-src="rowCollection" class="table table-striped">
<thead>
<tr>
<th st-sort="sku">SKU</th>
<th st-sort="skuSupplier">SKU proveedor</th>
<th st-sort="name">Descripción</th>
<th st-sort="cantidad">Cantidad</th>
<th st-sort="precio">Precio unitario</th>
<th st-sort="total">Total</th>
</tr>
<tr>
<th colspan="5"><input st-search="" class="form-control" placeholder="Buscar producto ..." type="text"/></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in displayedCollection">
<td><markdown value="row.sku"></markdown></td>
<td><markdown value="row.skuSupplier"></markdown></td>
<td><markdown value="row.name"></markdown></td>
<td><markdown value="row.cantidad"></markdown></td>
<td><markdown value="row.precio"></markdown></td>
<td><markdown value="row.total"></markdown></td>
<td>
<button type="button" ng-click="removeItem(row)" class="btn btn-sm btn-danger">
<i class="glyphicon glyphicon-remove-circle"></i>
</button>
</td>
</tr>
</tbody>
</table>

Combine two Knockout Examples

I am trying to get two examples from knockout.com working and I have yet to figure it out. Any help would be greatly appreciated!
http://jsfiddle.net/gZC5k/2863/
When running this project and using a debugger I get an error:
Uncaught ReferenceError: Unable to process binding "foreach: function (){return linesa }"
Message: linesa is not defined
From the original example I changed lines to linesa to see if anything else was screwing it up. It still did not like linesa
My main goal is to get these two samples working together. The Add a contact button works but the Add product does not work.
Thank you!
<div class='liveExample'>
<h2>Contacts</h2>
<div id='contactsList'>
<table class='contactsEditor'>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Phone numbers</th>
</tr>
<tbody data-bind="foreach: contactsa">
<tr>
<td>
<input data-bind='value: firstName' />
<div><a href='#' data-bind='click: $root.removeContact'>Delete</a></div>
</td>
<td><input data-bind='value: lastName' /></td>
<td>
<table>
<tbody data-bind="foreach: phones">
<tr>
<td><input data-bind='value: type' /></td>
<td><input data-bind='value: number' /></td>
<td><a href='#' data-bind='click: $root.removePhone'>Delete</a></td>
</tr>
</tbody>
</table>
<a href='#' data-bind='click: $root.addPhone'>Add number</a>
</td>
</tr>
</tbody>
</table>
</div>
<p>
<button data-bind='click: addContact'>Add a contact</button>
<button data-bind='click: save, enable: contactsa().length > 0'>Save to JSON</button>
</p>
<textarea data-bind='value: lastSavedJson' rows='5' cols='60' disabled='disabled'> </textarea>
</div>
<div class='liveExample'>
<table width='100%'>
<thead>
<tr>
<th width='25%'>Category</th>
<th width='25%'>Product</th>
<th class='price' width='15%'>Price</th>
<th class='quantity' width='10%'>Quantity</th>
<th class='price' width='15%'>Subtotal</th>
<th width='10%'> </th>
</tr>
</thead>
<tbody data-bind='foreach: linesa'>
<tr>
<td>
<select data-bind='options: sampleProductCategories, optionsText: "name", optionsCaption: "Select...", value: category'> </select>
</td>
<td data-bind="with: category">
<select data-bind='options: products, optionsText: "name", optionsCaption: "Select...", value: $parent.product'> </select>
</td>
<td class='price' data-bind='with: product'>
<span data-bind='text: formatCurrency(price)'> </span>
</td>
<td class='quantity'>
<input data-bind='visible: product, value: quantity, valueUpdate: "afterkeydown"' />
</td>
<td class='price'>
<span data-bind='visible: product, text: formatCurrency(subtotal())' > </span>
</td>
<td>
<a href='#' data-bind='click: $parent.removeLine'>Remove</a>
</td>
</tr>
</tbody>
</table>
<p class='grandTotal'>
Total value: <span data-bind='text: formatCurrency(grandTotal())'> </span>
</p>
<button data-bind='click: addLine'>Add product</button>
<button data-bind='click: save'>Submit order</button>
</div>
var initialData = [
{ firstName: "Danny", lastName: "LaRusso", phones: [
{ type: "Mobile", number: "(555) 121-2121" },
{ type: "Home", number: "(555) 123-4567"}]
},
{ firstName: "Sensei", lastName: "Miyagi", phones: [
{ type: "Mobile", number: "(555) 444-2222" },
{ type: "Home", number: "(555) 999-1212"}]
}
];
var ContactsModel = function(contactstest) {
var self = this;
self.contactsa = ko.observableArray(ko.utils.arrayMap(contactstest, function(contact) {
return { firstName: contact.firstName, lastName: contact.lastName, phones: ko.observableArray(contact.phones) };
}));
self.addContact = function() {
self.contactsa.push({
firstName: "",
lastName: "",
phones: ko.observableArray()
});
};
self.removeContact = function(contact) {
self.contactsa.remove(contact);
};
self.addPhone = function(contact) {
contact.phones.push({
type: "",
number: ""
});
};
self.removePhone = function(phone) {
$.each(self.contactsa(), function() { this.phones.remove(phone) })
};
self.save = function() {
self.lastSavedJson(JSON.stringify(ko.toJS(self.contactsa), null, 2));
};
self.lastSavedJson = ko.observable("")
};
ko.applyBindings(new ContactsModel(initialData));
function formatCurrency(value) {
return "$" + value.toFixed(2);
}
var CartLine = function() {
var self = this;
self.category = ko.observable();
self.product = ko.observable();
self.quantity = ko.observable(1);
self.subtotal = ko.computed(function() {
return self.product() ? self.product().price * parseInt("0" + self.quantity(), 10) : 0;
});
// Whenever the category changes, reset the product selection
self.category.subscribe(function() {
self.product(undefined);
});
};
var Cart = function() {
// Stores an array of lines, and from these, can work out the grandTotal
var self = this;
self.linesa = ko.observableArray([new CartLine()]); // Put one line in by default
self.grandTotal = ko.computed(function() {
var total = 0;
$.each(self.linesa(), function() { total += this.subtotal() })
return total;
});
// Operations
self.addLine = function() { self.linesa.push(new CartLine()) };
self.removeLine = function(line) { self.linesa.remove(line) };
self.save = function() {
var dataToSave = $.map(self.linesa(), function(line) {
return line.product() ? {
productName: line.product().name,
quantity: line.quantity()
} : undefined
});
alert("Could now send this to server: " + JSON.stringify(dataToSave));
};
};
ko.applyBindings(new Cart());
ViewModel is a ContactsModel, since ContactsModel does not have a linesa property, it cannot render the contents of the table.
<tbody data-bind='foreach: linesa'>
this is the offending line.
You are working with 2 ViewModels actually, the Cart ViewModel and the Contacts ViewModel.
you need to make a new ViewModel that implements both ViewModels and you can bind the views using with binding.
Code:
function CombinedViewModel(){
this.cart=new Cart();
this.contact=new Contact();
}
ko.appyBindings(new CombinedViewModel());
and for the bindings
<div data-bind="with:cart"><!-- cart html view goes here --></div>
<div data-bind="with:contact"><!-- contact html view goes here --></div>

Knockout js. Get element from table and set it as current.

I have some trouble. I write a web app with geo services.
There is a ViewModel thar contains an observableCollection of 'Queuers' and the propery SelectedItem that represent a 'Queue' from that collection. The value of SelectedItem sets from table:
<tbody data-bind="foreach: Queuers">
<tr>
<td class="text-center">
<span data-bind="text: Number"></span>
</td>
<td class="text-center">
<i class="icon-flag icon-2x" data-bind="style: { color: Color }"></i>
</td>
<td class="text-center">
<span data-bind="text: Length"></span>
</td>
<td class="text-center">
<span data-bind="text: Resolution"></span>
</td>
<td class="text-center">
<button style="background: none; border: none" data-bind="click: $root.getData" #*onclick="$('#myModal').modal()"*#>
<i class="icon-thumbs-up-alt icon-2x"></i>
</button>
</td>
<td class="text-center">
<button style="background: none; border: none" data-bind="click: $root.remove">
<i class="icon-trash icon-2x"></i>
</button>
</td>
</tr>
</tbody>
and ViewModel:
var Query = function (number, color, length, res, data) {
this.Number = ko.observable(number);
this.Color = ko.observable(color);
this.Length = ko.observable(length);
this.Resolution = ko.observable(res);
this.Data = ko.observable(data);
};
function TwoDimViewModel() {
var self = this;
self.SelectedItem = ko.observable();
self.SelectedColor = ko.observable(); //just for test
self.Queuers = ko.observableArray();
self.remove = function (q) {
self.Queuers.remove(q);
};
self.getData = function (q) {
self.SelectedItem = q;
self.SelectedColor = q.Color(); //just for test
self.addQ = function (q) {
self.Queuers.push(q);
};
self.removeAll = function () {
self.Queuers([]);
};
}
As you see, there is some logic to manipulate with ObservaleCollection. And all work perfect expect one:
self.getData = function (q) {
self.SelectedItem = q;
}
I want for in my
<div class="row" data-bind="visible: Queuers().length >= 1">
<button class="btn btn-default" onclick="clearAll()">Clear all</button>
<br />
Current selected id: <span data-bind="text: SelectedItem() ? SelectedItem().Number() : 'select element'"></span>
<br />
Выбран цвет: <span data-bind="text: SelectedColor() ? SelectedColor: 'nulll'"></span>
</div>
there will be current value of SelectedElement.
And how to get access to is property (Number, Color, etc...)
Change:
self.SelectedItem = q;
self.SelectedColor = q.Color();
To:
self.SelectedItem(q);
self.SelectedColor(q.Color());
Reference: http://knockoutjs.com/documentation/observables.html#observables

Categories

Resources