Master / Detail Functionality in kogrid - javascript

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

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 });
};

Where can I get Angular ui-grid selected items

Testing out Angular ui-grid (ng-grid v.3.0). Can not for the life of me find the selected row. I just want to grab the rows or even row ID of row when a user clicks it. Found the top comment here but I think this is outdated: Getting select rows from ng-grid?
Does anyone know where the gridOptions.selectedItems is being stored in 3.0?
Is this what your are looking for ?
http://ui-grid.info/docs/#/tutorial/210_selection
Activate grid selection capabilities with the ui-grid-selection tag (and ui.grid.selection module registration in your app
register gridApi and use gridApi.selection to access getSelectedRows()
In addition to the steps above https://stackoverflow.com/a/26188783/2658127, you might have to invoke it through a ng-click event to get the actual value/object. At least that's how I had it working.
Eg:
$scope.selectRow = function(){
$scope.gridApi.selection.getSelectedRows();
};
And call selectRow() from the template.
This is for anybody who have been confused like I did, considering the fact that ui-grid does not have the best documentation (specially for this select portion).
The easiest approach is:
Register the gridApi by adding this your controller:
$scope.gridOptions.onRegisterApi = function(gridApi) {
$scope.myGridApi = gridApi;
};
Access the array of selected items:
$scope.myGridApi.selection.getSelectedRows();
With grid ui you have to use the selection.on.rowSelectionChanged to update a scope variable that store the selectedItem.
In this way you can use the value in a binding expression.
var SelectController = function($scope) {
...
$scope.selectedItem = null;
$scope.gridOptions = {
data : 'articles',
enableRowSelection : true,
multiSelect : false,
enableRowHeaderSelection : false,
...
};
$scope.gridOptions.onRegisterApi = function(gridApi) {
// set gridApi on scope
this.$scope.gridApi = gridApi;
}.bind(this);
$scope.gridOptions.onRegisterApi = function(gridApi) {
// set gridApi on scope
this.$scope.gridApi = gridApi;
this.$scope.gridApi.selection.on.rowSelectionChanged($scope,
function(row) {
this.$scope.selectedItem = row.entity;
}.bind(this));
}.bind(this);
Use a an array instead of a plain object if you need multiple selection.

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;

IgniteUI combo box datasource updates with knockout

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/

Categories