IgniteUI combo box datasource updates with knockout - javascript

I have created a igComboBox with it's datasource set as an observableArray. When I add items to the array, I would like the datasource of the combobox to automatically pull in the new values, without having to set the self.datasource:sourceListArray() explicitly. How can I achieve this?
self.sourceListArray = ko.observableArray();
$("#dataSource").igCombo({
allowCustomValue: false,
showDropDownButton: true,
enableClearButton: false,
dataSource: self.sourceListArray(),
nullText: "Select Data Source",
selectionChanged: self.dataSourceChanged
});
function PopulateSourceList(sourceList) {
for (var i = 0; i < sourceList.length; i++) {
self.sourceListArray.push(sourceList[i].ServiceName);
}
$("#dataSource").igCombo({ dataSource: self.sourceListArray() }); //don't want this
}

Your current sample is not really using the Knockout support for the Ignite UI Combo. Have a look at this sample for KnockoutJS Binding, by comparison you are initializing the Combo the default way, not going through the Knockout binding process (where our handler kicks in). The solution is simple - define the combo like this:
<div id="dataSource" data-bind="igCombo: {
allowCustomValue: false,
showDropDownButton: true,
enableClearButton: false,
dataSource: self.sourceListArray(),
nullText: 'Select Data Source',
selectionChanged: self.dataSourceChanged
}"></div>
And then everything will just work - http://jsfiddle.net/damyanpetev/athF2/

Related

How to refresh knockout grid after AJAX API Call

I am working in an MVC 5 / Knockout environment. My View is loaded initially from the ViewModel supplied by a standard MVC 5 Controller. I have a knockout grid as part of this view. The grid is correctly populated based on the ViewModel contents.
On a user button push, a Web API call is made and returns successfully. I want to use the data returned from the API call to update the Knockout observable array which is bound to the knockout grid. I can see the knockout observable array is correcty updated, but the knockout grid is never refreshed. The knockout observalbe array I write to with the results of the API call is the same array that gets written to when the View is first loaded.
This is teh code at the top of the .cshtml view:
<script>
$(function () {
var inputData = ko.mapping.toJS(#Html.Raw(HelperFunctions.ToJson(Model)));
var dom = document.getElementById("AWBSNode");
var obj = new AreasModel(inputData);
ko.applyBindings(obj, dom);
});
</script>
AWBSNode is the topmost div in my cshtml. Below is the html for my Grid
<div id="koGridPanel" class="panel panel-default top-buffer">
<div class="panel-heading">AWBS - Areas</div>
<div class="koGrid" data-bind="koGrid: gridOptions"></div>
</div>
Below is the relevant JS of my View Model / grid config / binding
var AreasModel = function(data) {
var self = this;
var apiCall = new APICaller();
.
.
.
self.AllAWBSAreas = ko.observableArray(
ko.utils.arrayMap(data.Areas, function(x) {
return new NewAWBSAreaModel(x);
})
);
.
.
.
this.gridOptions = {
footerRowHeight: 35,
beforeSelectionChange: function (rowItem) {
self.selectAreaToEdit(rowItem);
},
disableTextSelection: false,
keepLastSelected: false,
multiSelect: false,
displaySelectionCheckbox: false,
data: self.AllAWBSAreas,
columnDefs: [
{ field: 'Name', displayName: 'Name' },
{ field: 'Description', displayName: 'Description' }
]
};
.
.
.
Below is the API Call I make (I am using a wrapper function but that part works fine as I do come in to the success path and the data is there
apiCall.CallAPI(
url,
dom,
true,
null,
function (successData) {
self.AllAWBSAreas(ko.utils.arrayMap(successData.Items, function (x) {
return new NewAWBSAreaModel(x);
});
);
I also tried the alternative approach of
apiCall.CallAPI(
url,
dom,
true,
null,
function (successData) {
self.AllAWBSAreas(successData.Items);
.
.
.
.
I have tried calling valueHasMutated() on the AllAWBSAreas entity. There is no problem with the API call and its return data as this pattern works fine in all other aspects of the project. The symptom I see is that the grid in the UI is "affected" but not updated. The tidy blue banner at the top goes blank but the data remains unchanged.
The answer turned out to be a problem with the ladda spinner. The knockout grid would not update if the spinner was attached to the knockout grid. I moved the spinner to nearby piece of UI and all worked. Thanks for those who took the time to look at / help with this issue.

Dynamic default value for Kendo Grid

I want an auto increment column in my Kendo Grid. This field isn't server side auto increment, because I want the user to see the value and be able to change it.
My current solution is to add a click attribute to Create button and loop over rows to find the highest value and increment it.
But how can I insert this value inside the newly created row? Click event happens before the new row is created.
So there is two possible solution:
Have a variable as default value and update it in my JS code.
Access the newly created row somehow, and update the value.
This is my JS code:
function createClick(id) {
var grid = $("#" + id).data('kendoGrid');
var highestRadif = 0;
grid.tbody.find('>tr').each(function () {
var dataItem = grid.dataItem(this);
var radif = dataItem.SRadifReqR;
highestRadif = highestRadif < radif ? radif : highestRadif;
})
alert(++highestRadif);
}
You can use Grid's edit event to add your new generatedId value to new Grid's model.
This is some explanation from their documentation:
Edit
fired when the user edits or creates a data item.
e.container jQuery, jQuery object of the edit container element, which wraps the editing UI.
e.model kendo.data.Model, The data item which is going to be edited. Use its isNew method to check if the data item is new
(created) or not (edited).
e.sender kendo.ui.Grid, The widget instance which fired the event.
I suppose your click have something like this
//generate id code
vm.newId = ++highestRadif; // we need to store generated Id
grid.addRow();
then on edit event
edit: function(e) {
var model = e.model; // access edited/newly added model
// model is observable object, use set method to trigger change event
model.set("id", vm.newId);
}
Note: Your schema model's field must set property editable: true, due to enable us to change model field value using set method. Also if your field schema have validation required, you need to remove it.
model: {
id: "ProductID",
fields: {
ProductID: { editable: true, nullable: true },
}
}
Sample
I was able to put a function in the datasource schema for this.
schema: {
model: {
id: "id",
fields: {
currencyType: { defaultValue: getDefaultCurrency },
invoiceDate: { type: "date" }
}
}
}
function getDefaultCurrency() {
return _.find(vm.currencyTypes, { id: vm.currencyId });
};

Master / Detail Functionality in kogrid

I want to implement Master / Detail Functionality in kogrid. So that when I select any field of first grid table all the other details will be shown in next detail grid.
Can anybody have any hint how to implement this.
A create a master/detail grid set you need to use a ko.computed to select/filter the detail.
You need 3 observable arrays and 1 computed.
var model = {
parent: ko.observableArray(),
details: ko.observableArray(),
selectedParents: ko.observableArray()
};
model.selectedDetails = ko.computed( function() {
var selectedParent = this.selectedParents()[0];
if ( !selectedParent ) {
return [];
}
return this.details().filter( function(item) {
// define filter comparison here
} );
}, model );
In your markup, define 2 koGrids
<div data-bind="koGrid: {
data: parent,
multiSelect: false,
selectedItems: selectParents }"></div>
<div data-bind="koGrid: { data: selectedDetails } "></div>
koGrid will populate the selectedItems observableArray with Zero or One item. The computed will execute a filter over the children which the second grid is bound to.
I have omitted the columnDef data bind part from breivity.
If you have an AJAX query to run for the details array, then use a subscription against the "parent" observable, change selectDetails to a straight observableArray and set its contents in the AJAX callback
See this jsFiddle for a basic example

ng-grid change sorting order onchange of drop down

I am using ng-grid , i have implemented search functionality on it but i want to change orderby option by changing drop down value.
I wish to provide drop down on change of its value data soting should happen.
by default Sort-functionality is there which works on click of table heading but i need to change sorting order on change of dropdown.
This code i got from somewhere but i dont know how to use it ?
$scope.gridOptions = {
data: 'gridData',
columnDefs: [
{field: 'name', displayName: 'Name'},
{field:'ageWord', displayName: 'Age'}
],
sortInfo: {
fields: ['age'],
directions: ['asc']
}
};
You need to define values for the sortInfo and useExternalSorting of your grid options, like this:
$scope.gridOptions.useExternalSorting = true;
$scope.gridOptions.sortInfo = {
fields: [$scope.selectedDropDownOption], // <-- or whatever variable used to store selected option from dropdown
directions: ['asc']
};
e.g.: if you want to sort by name, you could set
sortInfo: { fields: ['name'], directions: ['asc']}
this would order your grid by name and ascending
you also want to set useExternalSorting = true in your gridOptions.
i suggest you have a look at the docu and examples pages
I used following code ,,,
HTML :
<input type="text" ng-model="sortColumn"></input>
<button type="button" class="btn" ng-click="updateSortInfo()">Sort</button>
aap.js ::
$scope.updateSortInfo = function() {
$scope.gridOptions.sortBy($scope.sortColumn);
}
Reached here while searching for solution of similar thing. After trying all options I have applied this.
//Disable Grid Ui Sorting through header
$scope.gridOptions.enableSorting = false;
//Apply angular 'orderBy' filter to data for grid ui
$scope.resultSetTable = $filter('orderBy')($scope.gridData, 'YOUR_SORT_COLUMN');
// Apply data to grid ui
$scope.gridOptions.data = $scope.resultSetTable;

Ext js grid remove selection model

I have a situation where I need to dynamically add or remove grids selection model.
Searching the documentation I see that the selection model doesn't have a destroy() method or anything similar. How can I remove or destroy a selection model from a grid in ext js 4.x.?
If this is not possible I still have an option to revert some functionallity and dynamically add the selection model to an already created grid. But I'm also not sure if this is possible.
I'd suggest to disable the selection model instead of destroying it.
You can clear the current selection (deselectAll) and lock the selection model to prevent further selection (setLocked):
selModel.deselectAll();
selModel.setLocked(true);
As you're using a checkbox selection model, you'll also need to hide the corresponding column which is added to the grid:
grid.headerCt.child('gridcolumn[isCheckerHd]').hide();
Selection models are not designed to be replaced, so... it's gonna be complicated!
You'd have to reproduce the initialization of the sel model, unwire the previous one, and rewire the new one...
Here's an example that works in substituting a row selection model for a checkbox model. It may still contains memory leaks from listeners registered by the first selection model that I would have forgot. The creation of the new selection model relies on the getSelectionModel method of the grid, which implements the disableSelection, simpleSelect, and multiSelect options of the grid (see the code).
Ext.widget('grid', {
renderTo: Ext.getBody()
,store: ['Foo', 'Bar', 'Baz']
,selType: 'checkboxmodel'
,columns: [{
dataIndex: 'field1'
,text: "Name"
}]
,listeners: {
selectionchange: function(sm, records) {
var grid = sm.view.up(),
item = grid.down('tbtext');
if (records.length) {
item.setText(
'Selection: ' + Ext.pluck(Ext.pluck(records, 'data'), 'field1').join(', ')
);
} else {
item.setText('No selection');
}
}
}
,tbar: [{
text: "Replace selection model"
,handler: function(button) {
var grid = button.up('grid'),
headerCt = grid.headerCt,
checkColumn = headerCt.down('[isCheckerHd]'),
view = grid.view,
previous = grid.selModel,
sm;
// try to clean up
previous.deselectAll();
previous.destroy();
// sel model doesn't clear the listeners it has installed in its
// destroy method... you'll have to chase the listeners that are
// installed by the specific type of sel model you're using
if (previous.onRowMouseDown) {
view.un('itemmousedown', previous.onRowMouseDown, previous);
}
if (previous.onRowClick) {
view.un('itemclick', previous.onRowClick, previous);
}
// clear references
delete grid.selModel;
delete view.selModel;
// create another selModel
grid.selType = 'rowmodel';
//grid.disableSelection = true;
sm = grid.getSelectionModel();
// assign new sel model
view.selModel = sm;
sm.view = view;
// remove checkbox model column
if (checkColumn) {
headerCt.remove(checkColumn);
}
// init sel model is trigerred in view render events, so we must do it
// now if the view is already rendered
if (view.rendered) {
sm.beforeViewRender(view);
sm.bindComponent(view);
}
// finally, refresh the view
view.refresh();
}
}]
// a place to display selection
,bbar: [{
xtype: 'tbtext'
,text: 'No selection'
}]
});

Categories