Bind Kendo UI grid dataSource to combobox - angularjs

I have a Kendo UI grid that contains Name Objects, when I select a row I want to populate a form below. Currently the text inputs and date-picker work fine. But I combo box only has one way binding. I can change the value in the grid, but when I select a new row the value of the combobox doesnt change.
HTML
<div id="nd-names-tab" ng-controller="nd-names-controller">
<div id="nd-names-grid-section">
<div id="nd-names-grid"
kendo-grid="namesGrid"
k-data-source="namesData"
k-columns="nameGridColumns"
k-selectable="true"
k-reorderable="true"
k-on-change="selectedName = data"
k-toolbar="[
{ 'name': 'addName', template: '<button data-ng-click=\'addName()\' class=\'k-button\'>Add</button>' },
{ 'name': 'deleteName', template: '<button data-ng-click=\'deleteName()\' class=\'k-button\'>Delete</button>' }
]" >
</div>
</div>
<div id="nd-names-input-section">
<label>Name: <input type="text" class="k-textbox" ng-model="selectedName.lname"/></label>
<input type="text" class="k-textbox" ng-model="selectedName.fname" /> <br/>
<label>DOB: <input id="datepicker" ng-model="selectedName.dob"/></label>
<label>Gender: <input id="gender" ng-model="selectedName.gender"/></label> <br />
<label>Address: <input type="text" class="k-textbox" style="width: 200px" ng-model="selectedName.addr"/></label>
</div>
</div>
JS File
$("#datepicker").kendoDatePicker({
format: "dd/MM/yyyy"
});
$("#gender").kendoComboBox({
dataTextField: "text",
dataValueField: "value",
dataSource: [
{ text: "Male", value: "Male" },
{ text: "Female", value: "Female" },
],
filter: "contains",
suggest: true
});
Angular Controller
app.controller('nd-names-controller', function($scope){
$scope.namesData = new kendo.data.ObservableArray([
{ fname: 'Joe', lname: 'Clark', addr: '1565 Main Rd.', dob: '14/08/1990', gender: 'Male'},
{ fname: 'Bob', lname: 'Smith', addr: '123 Main St.', dob: '23/03/1992', gender: 'Male'},
{ fname: 'Jane', lname: 'Smith', addr: '123 Main St.', dob: '25/06/1991', gender: 'Female'},
{ fname: 'Jane', lname: 'Smith', addr: '123 Main St.', dob: '25/06/1991', gender: 'Female'},
{ fname: 'Jane', lname: 'Smith', addr: '123 Main St.', dob: '25/06/1991', gender: 'Female'}
]);
$scope.nameGridColumns = [
{field: "fname", title: "First Name", width: "*" },
{field: "lname", title: "Last Name", width: "*" },
{field: "addr", title: "Address", width: "*" },
{field: "dob", title: "DOB", width: "*" },
{field: "gender", title: "Gender", width: "*" }
];
$scope.addName = function(e){
this.namesGrid.dataSource.add( { fname: '', lname: '', addr: '', dob: '', gender: ''} );
}
});
I am not sure how I am suppose to use angular to two way bind a combo box.

You are declaring the kendo combobox using Jquery. Instead create an options in you controller and pass it to kendo directive.
Directive:
<select id="slots" kendo-drop-down-list k-options="slotsOptions" style="width: 200px"></select>
In you angular controller
var dataSlotDuration = [
{ text: "10", value: "10" },
{ text: "15", value: "15" },
{ text: "20", value: "20" },
{ text: "30", value: "30" },
{ text: "60", value: "60" }
];
function onSelectSlotDuration(e) {
var dataItem = this.dataItem(e.item.index());
// this is the seled value from drop-drop-list
$scope.selectedSlotDuration = dataItem.value;
}
$scope.slotsOptions = {
dataSource: {
data: dataSlotDuration
},
dataTextField: "text",
dataValueField: "value",
optionLabel: "Choose Slot Duration...",
select: onSelectSlotDuration
}
Its in the Kendo Docs

Related

React-table dynamic drop down reusable custom filter

I've got a react-table where I want to add some custom filtering
What I'm trying to achieve is a drop-down selector which is dynamically populated with all the available choices
I'm almost there and have a working solution but what I'd really like to do is make my customFilter reusable for each of the three fields, first name, last name and age - currently it works but is hardcoded for each value
So this line
.map(item => item.lastName)
Needs to be something like
.map(item => item.{accessor})
That doesn't work but idea is that I could get the accessor value for each of the fields and then this would be truly dynamic and reusable
const customFilter = ({ filter, onChange }) => {
return (
<select
onChange={event => onChange(event.target.value)}
style={{ width: "100%" }}
value={filter ? filter.value : "all"}
>
<option value="all">Show All</option>
{testData
.map(item => item.lastName)
.filter((item, i, s) => s.lastIndexOf(item) == i)
.map(function (value) {
log.debug('renderItem: ', value);
return (
<option key={value} value={value}>
{value}
</option>
);
})}
</select>
);
};
const testData = [
{ firstName: 'Aang', lastName: 'Smith', age: '19' },
{ firstName: 'Appa', lastName: 'Baker', age: '3' },
{ firstName: 'Asami', lastName: 'Smith', age: '19' },
{ firstName: 'Azula', lastName: 'Baker', age: '19' },
{ firstName: 'Bolin', lastName: 'Smith', age: '20' },
{ firstName: 'Jinora', lastName: 'Baker', age: '19' },
{ firstName: 'Katara', lastName: 'Smith', age: '8' },
{ firstName: 'Korra', lastName: 'Baker', age: '19' },
{ firstName: 'Lin Beifong', lastName: 'Smith', age: '19' },
{ firstName: 'Momo', lastName: 'Baker', age: '19' },
{ firstName: 'Mai', lastName: 'Smith', age: '8' },
{ firstName: 'Mako', lastName: 'Baker', age: '29' },
{ firstName: 'Naga', lastName: 'Smith', age: '19' },
{ firstName: 'Pabu', lastName: 'Baker', age: '19' },
{ firstName: 'Sokka', lastName: 'Smith', age: '39' },
{ firstName: 'Suki', lastName: 'Baker', age: '8' },
{ firstName: 'Tenzin', lastName: 'Smith', age: '19' },
{ firstName: 'Toph Beifong', lastName: 'Baker', age: '19' },
{ firstName: 'Ty Lee', lastName: 'Smith', age: '49' },
{ firstName: 'Uncle Iroh', lastName: 'Baker', age: '59' },
{ firstName: 'Varrick', lastName: 'Smith', age: '19' },
{ firstName: 'Zhu Li', lastName: 'Baker', age: '8' },
{ firstName: 'Zuko', lastName: 'Smith', age: '19' }
];
const columns = [
{
Header: "First Name",
accessor: "firstName",
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value) &&
row[filter.id].endsWith(filter.value)
}, {
Header: "Last Name",
id: "lastName",
accessor: d => d.lastName,
filterMethod: (filter, row) => {
return row[filter.id] === filter.value;
},
Filter: ({ filter, onChange }) =>
customFilter({ filter, onChange })
}, {
Header: "Age",
accessor: "age",
filterMethod: (filter, row) => {
return row[filter.id] === filter.value;
},
Filter: ({ filter, onChange }) =>
customFilter({ filter, onChange })
}
]
return (
<div>
<ReactTable
data={testData}
filterable
defaultFilterMethod={(filter, row) =>
String(row[filter.id]) === filter.value}
columns={columns}
defaultPageSize={10}
className="-striped -highlight"
/>
<br />
</div>
);
Found a solution
So for each of the columns filters I gave it a fieldName variable - I can then just call that to change the value and make this reusable
So this line
.map(item => item.lastName)
Becomes this
.map(item => item[fieldName])
Works great :-)
const customFilter = ({ fieldName, filter, onChange }) => {
return (
<select
onChange={event => onChange(event.target.value)}
style={{ width: "100%" }}
value={filter ? filter.value : "all"}
>
<option value="all">Show All</option>
{testData
.map(item => item[fieldName])
.filter((item, i, s) => s.lastIndexOf(item) == i)
.map(function (value) {
log.debug('renderItem: ', value);
return (
<option key={value} value={value}>
{value}
</option>
);
})}
</select>
);
};
const testData = [
{ firstName: 'Aang', lastName: 'Smith', age: '19' },
{ firstName: 'Appa', lastName: 'Baker', age: '3' },
{ firstName: 'Asami', lastName: 'Smith', age: '19' },
{ firstName: 'Azula', lastName: 'Baker', age: '19' },
{ firstName: 'Bolin', lastName: 'Smith', age: '20' },
{ firstName: 'Jinora', lastName: 'Baker', age: '19' },
{ firstName: 'Katara', lastName: 'Smith', age: '8' },
{ firstName: 'Korra', lastName: 'Baker', age: '19' },
{ firstName: 'Lin Beifong', lastName: 'Smith', age: '19' },
{ firstName: 'Momo', lastName: 'Baker', age: '19' },
{ firstName: 'Mai', lastName: 'Smith', age: '8' },
{ firstName: 'Mako', lastName: 'Baker', age: '29' },
{ firstName: 'Naga', lastName: 'Smith', age: '19' },
{ firstName: 'Pabu', lastName: 'Baker', age: '19' },
{ firstName: 'Sokka', lastName: 'Smith', age: '39' },
{ firstName: 'Suki', lastName: 'Baker', age: '8' },
{ firstName: 'Tenzin', lastName: 'Smith', age: '19' },
{ firstName: 'Toph Beifong', lastName: 'Baker', age: '19' },
{ firstName: 'Ty Lee', lastName: 'Smith', age: '49' },
{ firstName: 'Uncle Iroh', lastName: 'Baker', age: '59' },
{ firstName: 'Varrick', lastName: 'Smith', age: '19' },
{ firstName: 'Zhu Li', lastName: 'Baker', age: '8' },
{ firstName: 'Zuko', lastName: 'Smith', age: '19' }
];
const columns = [
{
Header: "First Name",
accessor: "firstName",
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value) &&
row[filter.id].endsWith(filter.value)
}, {
Header: "Last Name",
id: "lastName",
accessor: d => d.lastName,
filterMethod: (filter, row) => {
return row[filter.id] === filter.value;
},
Filter: ({ filter, onChange }) =>
customFilter({ fieldName:'lastName', filter, onChange })
}, {
Header: "Age",
accessor: "age",
filterMethod: (filter, row) => {
return row[filter.id] === filter.value;
},
Filter: ({ filter, onChange }) =>
customFilter({ fieldName:'age', filter, onChange })
}
]
return (
<div>
<ReactTable
data={testData}
filterable
defaultFilterMethod={(filter, row) =>
String(row[filter.id]) === filter.value}
columns={columns}
defaultPageSize={10}
className="-striped -highlight"
/>
<br />
</div>
);

How can I merge columns in UI-grid?

Is there any way to merge the columns of UI-grid to be appear as continuous row (without any column line in between). I have tried this
merge columns in ui grid
but this causes me loss of row data at row number number 1. Even more I want every alternate row to be merged.
Here is my Html
<div id="grid" ui-grid="gridOptions" ui-grid-move-columns ui-grid-resize-columns ui-grid-auto-resize class="grid"></div>
Here is my js code for grid
$scope.gridOptions = {
enableColumnResizing: true,
enableRowHeaderSelection: false,
enableGridMenu: true,
enableHorizontalScrollbar: 0,
enableVerticalScrollbar: 2,
enableColumnMenus: false,
enableRowSelection: true,
columnDefs: [
{
name: 'Code',
field: 'Code',
}, {
name: 'Title',
field: 'Title',
}, {
name: 'Visits',
field: 'Visit',
}, {
name: 'UsedVisits',
field: 'usedVisits',
}, {
name: 'Pending Visits',
field: 'pendingVisits',
}, {
name: 'Available Visits',
field: 'availableVisits',
}, {
name: 'Start Date',
field: 'StartDate',
}, {
name: 'End Date',
field: 'EndDate',
}, {
name: 'Status',
field: 'Status',
}
]
};
Please suggest me something,
Thank you
To implement it we can merge data while creating array for grid itself
using logic
originally we have array which we merge to show in grid so that in grid we can get merged data
$scope.myData = [{name: "1Abcd", age: "one", gender:2},
{name: "2Tom", age: "two", gender:1},
{name: "3Abcd", age: "three", gender:2},
{name: "4Abcd", age: "four", gender:2},
{name: "5Abcd", age: "five", gender:2},
{name: "6Abcd", age: "six", gender:2},
{name: "7Abcd", age: "seven", gender:2},
{name: "8Abcd", age: "eight", gender:2},
{name: "9Abcd", age: "nine", gender:2},
];
$scope.myDataNew =[] ;
for(var i=0;i<(($scope.myData.length/2)+1);i++){
var tempObj ={};
if($scope.myData[i*2] && $scope.myData[i*2].name && $scope.myData[i*2+1] &&$scope.myData[i*2+1].name){
tempObj.name =$scope.myData[i*2].name+$scope.myData[i*2+1].name ;
}
else if($scope.myData[i*2] && $scope.myData[i*2].name && !$scope.myData[i*2+1] ){
tempObj.name =$scope.myData[i*2].name;
}
if($scope.myData[i*2] && $scope.myData[i*2].age && $scope.myData[i*2+1] &&$scope.myData[i*2+1].age){
tempObj.age =$scope.myData[i*2].age+$scope.myData[i*2+1].age ;
}else if($scope.myData[i*2] && $scope.myData[i*2].age && !$scope.myData[i*2+1] )
{
tempObj.age =$scope.myData[i*2].age;
}
$scope.myDataNew.push(tempObj);
}
here is code pen for completed implementation
http://codepen.io/vkvicky-vasudev/pen/LRPNyL
If ant change required feel free to inform me

how to use Dojo to show/hide programmaticaly generated combo boxes by clicking radio buttons?

When I run my application, both combo boxes show. How to show one and hide the other one when clicking radio buttons?
I stored the state and region in a static json file and use xhrGet to get them.
i want to use dojo combo box for auto-complete.
var cboState;
var cboRegion;
dojo.xhrGet({
url: "../client/stemapp/widgets/samplewidgets/myProject/common.json",
handleAs: "json",
load: function (result) {
require([
"dojo/store/Memory",
"dijit/form/ComboBox",
"dojo/domReady!"
], function (Memory, ComboBox) {
var stateStore = new Memory({
data: result.states
});
var regionStore = new Memory({
data: result.regions
});
cboState = new ComboBox({
id: "state",
name: "state",
placeholder: "Select a State",
store: stateStore,
searchAttr: "name",
autocomplete: true
}, "state");
cboRegion = new ComboBox({
id: "region",
name: "region",
placeholder: "Select a Region",
store: regionStore,
searchAttr: "name",
autocomplete: true
}, "region");
});
}
});
domStyle.set(dom.byId('state'), "display", "block");
domStyle.set(dom.byId('region'), "display", "none");
On(query('.radio'),'change',function(){
query('.query').forEach(function(divElement){
domStyle.set(divElement, "display", "none");
});
domStyle.set(dom.byId(this.dataset.target), "display", "block");
});
<input class="radio" data-target="state" type="radio" name="selection" value="state" > State
<input class="radio" data-target="region" type="radio" name="selection" value="region" > Region
<div id="state" class="query"></div>
<div id="region" class="query"></div>
I let you deal with the creation of the combobox, but here is the code you were trying to write.
it is a simple and basic use of dojo/on
require([
'dojo/dom',
'dojo/dom-construct',
'dojo/dom-class',
'dojo/query',
'dojo/on',
'dojo/store/Memory',
'dijit/form/ComboBox',
'dojo/domReady!'
], function(dom, domConstruct, domClass, query, on, Memory, ComboBox) {
var stateStore = new Memory({
data: [{
name: "Alabama",
id: "AL"
}, {
name: "Alaska",
id: "AK"
}, {
name: "American Samoa",
id: "AS"
}, {
name: "Arizona",
id: "AZ"
}, {
name: "Arkansas",
id: "AR"
}, {
name: "Armed Forces Europe",
id: "AE"
}]
});
var regionStore = new Memory({
data: [{
name: "North Central",
id: "NC"
}, {
name: "South West",
id: "SW"
}]
});
var comboState = new ComboBox({
id: "stateSelect",
name: "state",
store: stateStore,
searchAttr: "name"
});
comboState.placeAt("state");
comboState.startup();
var comboRegion = new ComboBox({
id: "regionSelect",
name: "region",
store: regionStore,
searchAttr: "name"
});
comboRegion.placeAt("region");
comboRegion.startup();
on(query('.radio'), 'change', function(event) {
query('.query').forEach(function(divElement) {
domClass.add(divElement, 'hidden');
});
domClass.remove(dom.byId(event.target.value), 'hidden');
});
});
.hidden {
display: none
}
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/resources/dojo.css">
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit/themes/tundra/tundra.css">
<input class="radio" data-target="state" checked="true" type="radio" name="selection" value="state">State
<input class="radio" data-target="region" type="radio" name="selection" value="region">Region
<div id="state" class="query"></div>
<div id="region" class="query hidden"></div>

Angularjs UI Grid Totals per Row inside the row

{{ HelloWorld }}
I'm trying to access the values from other columns in the same row in angular-ui-grid. I have two question that are related.
How can I add the values from several columns in the same row to get a Total?
How can I use the row index to pass it as a parameter and remove the current row?
As you can see in the above image, the Totals that I'm looking for are only related to the integer values and not the initial string.
Also the Button with an X should delete the row when clicked. The rows are included in the grid dynamically.
I've gone through the UI Grid Tutorial but the examples don't show how to accomplish either of my questions.
My footer is working fine. It's configure to give a total but by column in the entire set of rows:
Here's a little bit of my code with what I've found so far:
var removeTemplate = '<button type="button" class="grid-remove btn btn-default btn-sm"><span class="glyphicon glyphicon-remove" aria-hidden="true" ng-click="removeRow($event, row.entity)"></span></button>';
$scope.gridAccountableHours = {
enableCellEditOnFocus: true,
showColumnFooter: true
};
$scope.gridAccountableHours.columnDefs = [
{ name: "contractCode", displayName: ""},
{ name: "hours1", displayName: "1", type: "number" },
{ name: "hours2", displayName: "2", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours3", displayName: "3", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours4", displayName: "4", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours5", displayName: "5", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours6", displayName: "6", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours7", displayName: "7", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours8", displayName: "8", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours9", displayName: "9", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours10", displayName: "10", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours11", displayName: "11", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours12", displayName: "12", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours13", displayName: "13", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours14", displayName: "14", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "hours15", displayName: "15", type: "number", aggregationType: uiGridConstants.aggregationTypes.sum },
{ name: "total", displayName: "Total" },
{ name: "remove", displayName: "", cellTemplate: removeTemplate }
];
$scope.removeRow = function ($event, entity) {
$event.stopPropagation();
$scope.gridAccountableHours.data.splice($scope.gridAccountableHours.data.indexOf(entity), 1);
};
I appreciate your time.
Totalling across the grid you could do with a function on the gridRow.
$scope.gridAccountableHours.forEach(function(rowEntity) {
rowEntity.total = function() {
var total = 0;
for( var 1 = 1; i++; i<=15 ){
total += this['hours'+i];
}
};
});
Your total column def should automatically bind to this total function. Refer http://ui-grid.info/docs/#/tutorial/106_binding
For the delete button, you're missing the appScope, refer http://ui-grid.info/docs/#/tutorial/305_appScope
Your template ng-click should be:
ng-click="grid.appScope.removeRow($event, row.entity)"

Kendo UI + Angular - v2014.2.903 vs v2014.3.1119 JSFiddle Issues

I am working on upgrading one of my Angular/Kendo UI projects from v2014.2.903 to v2014.3.1119. I have encountered a few instances where v2014.3.1119 breaks functionality that worked fine in v2014.2.903. I decided to create a couple JSFiddles to illustrate the issues, but unfortunately, the JSFiddle that points to v2014.2.903 doesn't seem to even recognize Kendo UI.
v2014.3.1119 JSFiddle (this works) ... http://jsfiddle.net/lejuan5150/w0711rdg/
v2014.2.903 JSFiddle (this doesn't work) ... http://jsfiddle.net/lejuan5150/4svqnaz6/
Both contain the same code and configuration aside from the version of Kendo UI they are referencing. Here is the code:
HTML:
<div>
<div data-ng-controller="personController">
<div
kendo-grid="personGrid"
k-options="personGridOptions"
k-ng-delay="personGridOptions">
</div>
<br />
First Name Combo Box:
<select
kendo-combo-box="firstNameComboBox"
k-options="firstNameComboBoxOptions"
k-ng-delay="firstNameComboBoxOptions"
k-ng-model="selectedPerson.firstName"
></select>
<br />
Last Name Combo Box:
<select
kendo-drop-down-list="lastNameDropDownList"
k-options="lastNameDropDownListOptions"
k-ng-delay="lastNameDropDownListOptions"
k-ng-model="selectedPerson.lastName"
></select>
</div>
JavaScript:
var app = angular
.module("app", [
"kendo.directives"
]);
app.controller("personController", [
"$scope",
personController
]);
function personController(
$scope
){
init();
function init(){
var personData = [{
firstName: "Joe",
lastName: "Smith",
status: "Active"
},{
firstName: "John",
lastName: "Smith",
status: "Active"
},{
firstName: "Travis",
lastName: "Smith",
status: "Expired"
}];
$scope.personDataSource = new kendo.data.DataSource({
data: personData
});
$scope.firstNamesData = [{
id: "Joe",
firstName: "Joe"
},{
id: "George",
firstName: "George"
},{
id: "John",
firstName: "John"
},{
id: "Travis",
firstName: "Travis"
}];
$scope.lastNamesData = [{
id: "Jones",
lastName: "Jones"
},{
id: "Smith",
lastName: "Smith"
}];
bindPersonGrid();
bindFirstNameComboBox();
bindLastNameDropDownList();
}
function bindPersonGrid(){
$scope.personGridOptions = {
dataSource: $scope.personDataSource,
selectable: "row",
dataBound: onPersonGridDataBound,
change: onPersonGridRowSelected
}
}
function onPersonGridDataBound(){
var grid = this;
var firstRow = grid.element.find("tbody tr:first");
grid.select(firstRow);
}
function onPersonGridRowSelected(
event
){
var grid = event.sender;
$scope.selectedPerson = grid.dataItem(grid.select());
$scope.$digest();
}
function bindFirstNameComboBox(){
$scope.firstNameComboBoxOptions = {
dataSource: $scope.firstNamesData,
dataTextField: "firstName",
dataValueField: "id"
};
}
function bindLastNameDropDownList(){
$scope.lastNameDropDownListOptions = {
dataSource: $scope.lastNamesData,
dataTextField: "lastName",
dataValueField: "id"
};
}
}
Does anyone know why the v2014.2.903 JSFiddle doesn't work?
I found the issue. Kendo v2014.2.903 doesn't like k-ng-delay when using a hard coded array of JavaScript objects.

Resources