Grid value not updating on changing dropdown in Knockout JS - javascript

Please find the updated fiddle in the comment section.
I have provided the HTML code and the ViewModel. On changing the value in drop down I want the pip value in grid to be updated. The pip value is getting calculated for new drop down value but the return is not able to bind the value to grid.

In order to make seats change in the UI on dropdownAValue change you need to declare empty observable array first:
self.seats = ko.observableArray();
And update it in the subscribe function instead of creating new observableArray every time:
self.seats([new PipCalculation(self.rates[0], self.rates[0].price, self.rates, self.newLot[0],currentlotvalue) ]);
See updated fiddle

well my answer will be addition to what Max Brodin has given .
We can further normalize you code by doing something like this
View model:
self.dropdownAValue = ko.observable(0.1);
self.seats = ko.observableArray([]);
var newItems = ko.utils.arrayMap(self.rates,function(item){
return new PipCalculation(item, item.price, self.rates, self.newLot[0], self.dropdownAValue)
});
self.seats(newItems);
//computed code
self.formattedPrice2 = ko.computed(function() {
//alert("hi");
var cur = self.rate().pair;
//var price = self.rate().price;
//alert(self.myQuote());
var price = self.myQuote();
var pip = 1;
var lot1 =currentlotvalue().lotSize;
Working fiddle here
Things to do :
There is no need to additionally write a subscribe for subscribing drop-down changes . All you need to do is send right DD value instance further in your case .
There is a performance hit as your are filling observablearray inside DD subscribe i.e every-time dropdown changes . That can be avoided by doing like i mentioned above.
Rather pushing into Observable array push into a normal array and the later using that array (performance improved) - max mentioned in his comments
There is a other way to do this like (i done previously like this)
self.seats([]);
var mutatedArray = self.seats();
ko.utils.arrayForEach(self.rates,function(item){
mutatedArray.push(new PipCalculation(item, item.price, self.rates, self.newLot[0],self.dropdownAValue)); // push to the array(normal array)
});
self.seats.valueHasMutated();
For more on this do refer my answer here .

Related

Get selected data array from kendo multiselect

I am trying to get an array of the selected items from my Kendo multiselect, which is in the editor template of a kendo grid.
The multiselect code:
#(Html.Kendo().MultiSelect()
.Name("Staff")
.DataValueField("ID")
.DataTextField("FullName")
.BindTo((System.Collections.IEnumerable)ViewData["Staff"])
.Events(events => events
.Change("onChange")
)
.HtmlAttributes(new { #class = "col-md-7 details-editor" })
)
I want to extract the selected items using JQuery - specifically, I want the DataValueField, which is an integer. I have tried several things, but have been unable to get the appropriate integers, rather than the index of the item in the ViewData collection. Some of the approaches I have tried.
var data = $("#Staff").data("kendoMultiSelect").dataItems();
var data = $("#Staff").data("kendoMultiSelect").value();
I don't really know what to do from here, how to use one of the above or a different route to obtain the correct int array.
Thanks for any help!
The answer is simpler than you would think.
$('#Staff').val();
That will return a comma delimited list of whatever is in your .DataValueField. In your case, a comma delimted list of 'ID'.
To get the IDs of the selected items, you can write your onChange method as follows:
var onChange = function(e) {
var arrayOfNames = this.value();
// Do other stuff here...
};
Documentation for the change event which gets fired can be found here.
I've also written a working example here.
Add a .Select("onSelect") event to the Multiselect and append the Value to hidden element every time when user selects the items using:
function onSelect(e) {
var item = e.item;
var text = item.text();
var $data = $('#myHidden');
$data.val($data.val() + text);
};

How can I get Index from Picker value selected?

I'm building an app with Appcelerator.
So I have used a Picker component to display a list of value.
Now I want to know what is the index of element that the user have selected.
So I'm try to do this:
var indexRow =$.comboDecription.getSelectedRow(0).getZIndex();
but I have undefined value.
You can use the following code:
// first get all columns
var columnsArray = $.comboDecription.getColumns();
// since it is a single column picker, so first index column's rows will be the ones you need.
var allRows = columnsArray[0].rows;
// get the title of first row, getSelectedRow(index) takes column index which is 0 in this case
var currentRowTitle = $.comboDecription.getSelectedRow(0).title;
// get the titles of all rows, these titles will be used to get the index of current title.
// use underscore library 'map' method to iterate over all rows and get their titles in an array
var allRowsTitles = _.map(allRows, function (row) {
return row.title;
});
// *** OR *** you can use underscore _.pluck method
var allRowsTitles = _.pluck(allRows, 'title');
// finally, this is the index of the selected picker row.
var currentSelectedRowIndex = allRowsTitles.indexOf(currentRowTitle);
I understand that it is the long process, but there are other ways too which depends on your implementation process. Nevertheless, I have shown you the stuffs you can do at run-time, and so you can do other things related to pickers.
gZindex() returns the layer where the view is positioned.
The change event return the current selected index.

Add/Remove Extjs combo value

I am newbie to extjs.I need to add/remove some values from extjs combo box base on some condition. I tried following code but no luck.
var obj =Ext.getCmp('filter');
var myArray=new Array();
myArray['id'] = 'a';
myArray['value'] = 'a';
var rec = new Ext.data.Record(myArray);
//obj.store.add(rec);
obj.store.removed(rec);
}
Use getById to find record for remove.
var combo = Ext.getCmp('filter');
combo.store.remove(combo.store.getById('a')); //typo: sotre corrected to store
combo.store.remove(combo.store.getById('a'));
obj.store.remove(rec);
removed is not a store function.
removed is a buffer array in which all removed recors are added.
if you're going to have a big store, you should keep this array empty, because removed objects are stored during all the session.
if the combo didn't change try to add store.sync() after adding or removing records

Kendo UI - Property Changed MVVM

I seem to be having issues databinding 'calculated' fields with Kendo UI.
I am attempting to do data-binding with several what I will call 'calculated' fields. I have a grid, several buttons, filters and some sorting on a page that are all using the same datasource, an observable array called 'allItems'. allItems is populated via a service call and sorted, manipulated and otherwise changed while the user is on the page via buttons.
There are several navigational buttons and several div's that are populated based on information in the previous item, current item and next item in accordance to the current filters and sorts applied. Those buttons contain information in them that is extracted from the previous, current and next items as they related to the allItems list (ie the objects are actually held in the allItems array and are in fact observable objects).
so in the viewmodel object I have something like this (please excuse short handing):
var viewmodel = kendo.observable({
var allItems = observablearray[]
var currentIndex = 1; //or other default value
var changeCurrentItem = function(){
var self = this;
//do some stuff
//stuff might include modification to allItems
self.set("currentIndex", someNewValue);
}
var previousItem = function(){
return self.get('allItems')[currentIndex - 1];
}
var currentItem = function(){
return self.get('allItems')[currentIndex];
}
var nextItem = function(){
return self.get('allItems')[currentIndex + 1];
});
return viewmodel;
The buttons and other info boxes are bound to previous,current and next Items. But this does not appear to work. I've had to make previous, current and nextItems copies of what lives in the allItems array and update those 3 objects at the same time. Not that big of a deal, but I just would like to, you know, not store copies of objects if I don't have to. I was hoping there might be a NotifyPropertyChanged("MyProperty") similiar to C#/Xaml that I missed while going through the API. This sort of functionality will be most useful to me for future tasks I have on my list due to some of the complexities of our calculated fields and the need to reducing memory consumption as devices get smaller.
Thanks for any help,
~David
Whenever a property of the view model changes, the change event is triggered.
To make this work in calculated fields, you need to access the relevant fields using ObservableObject.get(). See this section in the documentation.
2 possible problems.
1) How do you get items into allitems?
2) You should also .get("currentIndex") since that is the value that you update in changeCurrentItem
var currentItem = function(){
return self.get('allItems')[self.get('currentIndex')];
}
That should cause viewModel to fire its change event for thecurrentItem calculated field whenever allItems or currentIndex changes.
If all else fails, you can manually fire the change event by doing:
viewmodel.trigger("change", { field: "currentItem" });
viewmodel.trigger("change", { field: "previousItem" });
viewmodel.trigger("change", { field: "nextItem" });
which would be similar to calling NotifyPropertyChanged("currentItem") in XAML.

How Do I Make an Array of Objects a Reactive Data Source?

I have an array of objects. Say
var
sidelist = [
{
name:"asdf",
id:1234,
types:[...]
}
];
Every object is turned into a box on the page using this construct
Template.global.side = function(){
var obj = [], m;
m = 1;
for (var i in sides){
obj.push({
index : m,
object : sides[i]
});
}
return obj;
}
The HTML:
{{#each side}}
<div class="span{{this.index}}" id={{this.object.id}}>
<div class="side-head">{{this.object.name}}</div>
</template>
There is a function that creates and pushes a new object into the array. How do I make the row of boxes reactively update on the page when the array they depend on changes?
So when I add a new object a new box should appear.
If you want to use Dependencies, it can look like this:
var sidelist = ...;
var sidelist_dep = new Deps.Dependency;
Template.global.side = function(){
sidelist_dep.depend();
// Do your stuff here;
return ...;
};
// Important: call this every time you change sidelist,
// AFTER the change is made.
sidelist_dep.changed();
See: http://docs.meteor.com/#deps
In almost all cases, you should put the objects in a Meteor Collection instead of an array that is part of a reactive object. There are many reasons for this, including the following
Adding, removing, searching, and updating will all be faster
The reactivity will be on the element level instead of the array
Meteor won't re-render the whole set of objects when something is added or deleted - just the change
You can define a sort order on the collection, making it much more flexible than a fixed sequence
Take a look at Andrew Wilcox's isolate-value smart package:
https://atmosphere.meteor.com/package/isolate-value
The README contains the exact example of selectively rerendering relevant templates when values are added/removed from an array stored in a Session varaible.

Categories