Kendo Multiselect with AngularJS - angularjs

I want to set maxSelectedItems from a textbox value. Apart from that I want to reset kendo multiselect if textbox value change. I have tried below thing but it is not working.
<input type="hidden" ng-model="DTO.ProgramID" id="ProgramID" value="3">
<input class="form-control" data-val="true" id="ClassSize " maxlength="2" name="ClassSize " ng-model="DTO.ClassSize "type="text" ng-blur="OnClassSizeChange()">
<select id="CourseClientIDs" kendo-multi-select k-options="selectClientOptions" ng-model="DTO.CourseClientIDs"></select>
$scope.selectClientOptions = {
placeholder: "---Select Clients---",
dataTextField: "ClientFLName",
dataValueField: "ClientID",
valuePrimitive: true,
autoBind: false,
dataSource: {
type: "jsonp",
serverFiltering: true,
transport: {
read: {
url: "Home/ClientDataSource/",
cache: false
},
parameterMap: function (data, action) {
if (action === "read") {
if ($scope.DTO.ProgramID != undefined) {
return {
programID: $scope.DTO.ProgramID
};
}
} else {
return data;
}
}
}
}
};
$scope.OnClassSizeChange = function () {
if ($scope.DTO.ClassSize == 0) {
var message = "Class size cannot be 0.";
return false;
}else{
$scope.selectClientOptions.maxSelectedItems = $scope.DTO.ClassSize; //Not Working
$scope.selectClientOptions.dataSource.read(); //Not Working
}
return true;
};
I am trying angularjs with kendo first time. Please help me.

In the textbox define ngChange specify the function to execute when value change. Supposing ngModel for textbox is in $scope.nvm, try this:
$scope.nvm = 1; //value in textfield
$scope.setnvm = function(){//change maxSelectedItems and reset values
var ms = angular.element(document.getElementById("sems")).data("kendoMultiSelect");
ms.setOptions({
maxSelectedItems: $scope.nvm,
});
ms.value([]);
};

Related

Angular UI-Grid filtering

On my angular application I have a UI-Grid and a button to open a modal window.
In my gridoptions I enabled external filtering. But the problem is whenever I enter the filter field and press enter the button(modal window) is triggered and the modal opens up. I don't have any key events inside my controller.
Here are my gridoptions for the ui-grid:
gridOptions: uiGrid.IGridOptionsOf<any> = {
appScopeProvider: this,
data: [] as any[],
enableFiltering: true,
enablePaginationControls: false,
useExternalPagination: true,
minRowsToShow: 5,
useExternalSorting: true,
useExternalFiltering: true,
onRegisterApi: (gridApi: uiGrid.IGridApiOf<any>) => {
this.gridApi = gridApi;
this.gridApi.core.on.sortChanged(this.$scope, (grid: uiGrid.IGridInstanceOf<any>, columns: Array<uiGrid.IGridColumnOf<any>>) => this.sortRequests(grid, columns));
this.gridApi.pagination.on.paginationChanged(this.$scope, (newPage: number, pageSize: number) => this.changePage(newPage, pageSize));
this.gridApi.core.on.filterChanged(this.$scope, () => {
if (this.filterTimeout != undefined) {
this.$timeout.cancel(this.filterTimeout);
}
this.filterTimeout = this.$timeout(() => this.filterRequests(), 500);
});
},
I've set debuggers inside the filter methods but it doesn't get triggered by pressing enter only when you type a character.
Does anyone know what is triggering this button when enter is pressed?
UPDATE 1
<button class="btn btn-primary" ng-click="vm.open()" translate="country.headers.selectCountry"></button>
<div id="grid1" ui-grid="vm.gridOptions" ui-grid-pagination></div>
open() {
let instance = this.$uibModal.open({
templateUrl: 'app/common/controllers/html.html',
controller: 'controller as vm',
backdrop: 'static',
windowClass: 'country-modal',
resolve: {
programId: () => this.$stateParams['programId']
}
});
instance.result.then((dataGenerated: boolean) => {
if (dataGenerated) {
this.loadData();
}
});
}
UPDATE 2:
private filterRequests(): void {
let grid = this.gridApi.grid;
this.filtering = [];
for (let i = 0; i < grid.columns.length; i++) {
let column = grid.columns[i];
if (column.filters.length > 0) {
for (let j = 0; j < column.filters.length; j++) {
let filter = column.filters[j].term;
if (filter != undefined && filter != '')
this.filtering.push(column.field + '.contains("' + filter + '")');
}
}
}
this.loadRequests();
}
loadRequests(): void {
this.service
.get(
this.model.id,
{
params: {
page: this.pagingInfo.page,
pageSize: this.pagingInfo.pageSize,
sort: this.sorting,
filter: this.filtering
}
})
.then((data: any) => {
this.gridOptions.data = data.data;
this.gridHeight = (this.gridOptions.data.length + 2) * this.gridOptions.rowHeight;
this.pagingInfo.page = data.page;
this.pagingInfo.pageSize = data.pageSize;
this.pagingInfo.totalCount = data.totalCount;
});
}
With kinds regards, Brent

Pass md-on-demand to md-autocomplete

I would like display in md-autocomplete large list (around 50 000 records).
Autocomplete directive uses mdVirtualRepeat which provide infinity scrolling. I couldn't find way to pass md-on-demand option. Maybe someone find way to do that.
I really appreciate any help you can provide
UPDATE
I forget to share the code. I haven't problem with code performance but when list is rendering app is not responsive. In my opinion problem is in virtual rendering which still try to render whole list instead of visible part.
PS. I know $scope is bad but I'm using this example in angular-formly.
JS
$scope.to.options = [];
$scope.ctrl = {
selectedItem: null,
isDisabled: $scope.to.disabled,
noCache: $scope.to.noCache,
placeholder: $scope.to.placeholder || 'Wybierz element',
minLength: $scope.to.minLength || 0,
querySearch: querySearch,
searchTextChange: searchTextChange,
selectedItemChange: selectedItemChange,
delay: $scope.to.delay || 350,
options: []
};
if ($scope.to.dictId) {
dictionariesRepository.get($scope.to.dictId).then(function (res) {
$scope.ctrl.options = createOnDemandObject(res.Data.map(function (elem) {
return { value: elem[$scope.to.FieldVal], name: getLabel($scope.to.FieldFormula, elem) };
}));
var val;
if ((val = getValue())) {
var selected = $scope.ctrl.options.filter(function (elem) {
return elem.value == val;
})[0];
if (selected) {
$scope.ctrl.selectedItem = selected;
}
}
});
}
function createOnDemandObject(list) {
return {
list: list,
getLength: function () {
return this.list.length
},
getItemAtIndex: function (index) {
return this.list[index];
}
}
}
function searchTextChange(text) {
//$log.info('Text changed to ' + text);
}
function selectedItemChange(item) {
var getter = $parse($scope.options.key);
var setter = getter.assign;
setter($scope.model, item[$scope.to.FieldVal]);
}
function querySearch(query) {
var options = $scope.ctrl.options;
return query ? options.filter(createFilterFor(query)) : options;
}
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(elem) {
return (elem.name.indexOf(lowercaseQuery) === 0);
};
}
HTML
<md-autocomplete ng-disabled="ctrl.isDisabled" md-no-cache="ctrl.noCache" md-selected-item="ctrl.selectedItem" md-search-text-change="ctrl.searchTextChange(ctrl.searchText)"
md-delay="ctrl.delay"
md-search-text="ctrl.searchText" md-selected-item-change="ctrl.selectedItemChange(item)"
md-items="item in ctrl.querySearch(ctrl.searchText)"
md-on-demand
md-item-text="item.name" md-min-length="ctrl.minLength" placeholder="{{ctrl.placeholder}}">
<md-item-template>
<span md-highlight-text="ctrl.searchText" md-highlight-flags="^i">{{item.name}}</span>
</md-item-template>
<md-not-found>
Nie znaleziono pasującego wyniku dla "{{ctrl.searchText}}".
</md-not-found>
</md-autocomplete>

Field update after autocompletion with angularJS

I'm quite new to AngularJS and struggling a bit to have some input fields updated after an autocompletion event using google maps.
The idea is that when the user inputs his city/zip code, I would update 3 fields which are themselves linked to an object.
So far, I managed to have a working code except that sometimes the fields are not updated immediately : I have to autocomplete twice so that the good value will appear in the fields.
I've tweaked an existing angular directive in order to get what I want but since this is new to me, I dont know if I'm using the correct approach.
Below is the JS directive I use :
angular.module( "ngVilleAutocomplete", [])
.directive('ngAutocomplete', function($parse) {
return {
scope: {
details: '=',
ngAutocomplete: '=',
options: '=',
data: '='
},
link: function(scope, element, attrs, model) {
//options for autocomplete
var opts
//convert options provided to opts
var initOpts = function() {
opts = {}
if (scope.options) {
if (scope.options.types) {
opts.types = []
opts.types.push(scope.options.types)
}
if (scope.options.bounds) {
opts.bounds = scope.options.bounds
}
if (scope.options.country) {
opts.componentRestrictions = {
country: scope.options.country
}
}
}
}
initOpts()
//create new autocomplete
//reinitializes on every change of the options provided
var newAutocomplete = function() {
scope.gPlace = new google.maps.places.Autocomplete(element[0], opts);
google.maps.event.addListener(scope.gPlace, 'place_changed', function() {
scope.$apply(function() {
scope.details = scope.gPlace.getPlace();
//console.log(scope.details)
var HasCP = false;
for (var i=0 ; i<scope.details.address_components.length ; i++){
for (var j=0 ; j<scope.details.address_components[i].types.length ; j++){
if (scope.details.address_components[i].types[j] == 'postal_code' && scope.data.CP != 'undefined'){
scope.data.CP = scope.details.address_components[i].long_name;
HasCP = true;
} else if (scope.details.address_components[i].types[j] == 'locality' && scope.data.Ville != 'undefined') {
scope.data.Ville = scope.details.address_components[i].long_name;
} else if (scope.details.address_components[i].types[j] == 'country' && scope.data.Pays != 'undefined') {
scope.data.Pays = scope.details.address_components[i].long_name;
}
}
}
if (!HasCP){
var latlng = {lat: scope.details.geometry.location.lat(), lng: scope.details.geometry.location.lng()};
var geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
for (var i=0 ; i<results[0].address_components.length ; i++){
for (var j=0 ; j<results[0].address_components[i].types.length ; j++){
if (results[0].address_components[i].types[j] == 'postal_code' && scope.data.CP != 'undefined'){
scope.data.CP = results[0].address_components[i].long_name;
console.log('pc trouvé :' + scope.data.CP);
}
}
}
}
});
}
//console.log(scope.data)
scope.ngAutocomplete = element.val();
});
})
}
newAutocomplete()
//watch options provided to directive
scope.watchOptions = function () {
return scope.options
};
scope.$watch(scope.watchOptions, function () {
initOpts()
newAutocomplete()
element[0].value = '';
scope.ngAutocomplete = element.val();
}, true);
}
};
});
The matching HTML code is below :
<div class="form-group">
<lable>Code postal : </label>
<input type="text" id="Autocomplete" class="form-control" ng-autocomplete="cities_autocomplete" details="cities_autocomplete_details" options="cities_autocomplete_options" data="client" placeholder="Code postal" ng-model="client.CP" />
</div>
<div class="form-group">
<lable>Ville : </label>
<input type="text" id="Autocomplete" class="form-control" ng-autocomplete="cities_autocomplete" details="cities_autocomplete_details" options="cities_autocomplete_options" data="client" placeholder="Ville" ng-model="client.Ville" />
</div>
<div class="form-group">
<lable>Pays : </label>
<input type="text" class="form-control" name="Pays" ng-model="client.Pays" placeholder="Pays" />
</div>
You'll see that I pass the "client" object directly to my directive which then updates this object. I expected angular to update the html page as soon as the values of the client object are updated but I will not always be the case :
If I search twice the same city, the values are not updated
If I search a city, Google wont send me a zip code so I have to do another request to the geocoding service and I get the zipcode in return but while my client.CP field is correctly updated, changes are not visible in the CP input field until I do another search.
Thanks in advance for any advice on what I'm doing wrong.

AngularJS + Datatables + Dropdownlist

I'm using AngularJS to populate my datatable. What I want to know is how can I populate the datatable based on the dropdownlist
This is my dropdownlist
<div>
Get Users with Role:
<select id="ddlRole" data-ng-model="selectedRole" data-ng-change="populateDataTable()" data-ng-options="v.name for (k,v) in roles"></select>
<input type="hidden" value="{{selectedRole}}" />
</div>
This is my angular code
$scope.roles = [
{name: 'XXX' },
{name: 'YYY' }
];
$scope.selectedRole = $scope.roles[0];
//onchange event
$scope.populateDataTable = function () {
$scope.selectedRole = $scope.selectedRole.name;
RefreshDataTable(); //TODO
};
How can I change this to make an ajax call to retreive the data, populate the datatable based on the dropdownlist value and retain the value of dropdownlist as well.
I'm sure we can do this using JQuery but I dont want to mix these and make a mess. Is there any way I can acheive this using AngularJS?
Here is a simple data table directive:
appModule.directive('dataTable', [function () {
return function (scope, element, attrs) {
// apply DataTable options, use defaults if none specified by user
var options = {};
if (attrs.myTable.length > 0) {
options = scope.$eval(attrs.myTable);
} else {
options = {
"bStateSave": true,
"iCookieDuration": 2419200, /* 1 month */
"bJQueryUI": true,
"bPaginate": false,
"bLengthChange": false,
"bFilter": false,
"bInfo": false,
"bDestroy": true
};
}
// Tell the dataTables plugin what columns to use
// We can either derive them from the dom, or use setup from the controller
var explicitColumns = [];
element.find('th').each(function (index, elem) {
explicitColumns.push($(elem).text());
});
if (explicitColumns.length > 0) {
options["aoColumns"] = explicitColumns;
} else if (attrs.aoColumns) {
options["aoColumns"] = scope.$eval(attrs.aoColumns);
}
// aoColumnDefs is dataTables way of providing fine control over column config
if (attrs.aoColumnDefs) {
options["aoColumnDefs"] = scope.$eval(attrs.aoColumnDefs);
}
if (attrs.fnRowCallback) {
options["fnRowCallback"] = scope.$eval(attrs.fnRowCallback);
}
// apply the plugin
var dataTable = element.dataTable(options);
// watch for any changes to our data, rebuild the DataTable
scope.$watch(attrs.aaData, function (value) {
var val = value || null;
if (val) {
dataTable.fnClearTable();
dataTable.fnAddData(scope.$eval(attrs.aaData));
}
});
if (attrs.useParentScope) {
scope.$parent.dataTable = dataTable;
} else {
scope.dataTable = dataTable;
}
};
}]);
Then initialize it in your controller. Override fnServerData method, append your selected value (selected role) and filter data on server side.
$scope.overrideOptions = {
"bStateSave": true,
"iDisplayLength": 8,
"bProcessing": false,
"bServerSide": true,
"sAjaxSource": 'Data/Get',
"bFilter": false,
"bInfo": true,
"bLengthChange": false,
"sServerMethod": 'POST', ,
"fnServerData": function(sUrl, aoData, fnCallback, oSettings) {
var data = {
dataTableRequest: aoData,
selectedDropDownValue: $scope.selectedRole
};
$http.post(sUrl, data).success(function (json) {
if (json.sError) {
oSettings.oApi._fnLog(oSettings, 0, json.sError);
}
$(oSettings.oInstance).trigger('xhr', [oSettings, json]);
fnCallback(json);
});
}
};
var columnDefs = [
{
"mData": "id",
"bSortable": false,
"bSearchable": false,
"aTargets": ['tb-id']
},
{
"mData": "data",
"aTargets": ['tb-data']
}
];
Refresh the datatable on select change.
$scope.populateDataTable = function () {
if ($scope.dataTable) {
$scope.dataTable.fnDraw();
}
};
Html markup:
<table class="display m-t10px" data-table="overrideOptions" ao-column-defs="columnDefs">
<thead>
<tr>
<th class="tb-id"></th>
<th class="tb-data></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Hope above your code is in controller.
Inject $http and make a $http get or post call
$scope.populateDataTable = function () {
$scope.selectedRole = $scope.selectedRole.name;
$http.get('api/controller', function(result){
//response from the service call in result
});
};

kendo ui get id of checkbox when unchecked

i am using kendo ui tree view with check box
i want the check box's id when it is getting unchecked
this is kendo ui mine code
// var homogeneous contains data
$("#treeview").kendoTreeView({
checkboxes: {
checkChildren: false,
template:"# if(!item.hasChildren){# <input type='hidden' id='#=item.id#' parent_id='#=item.parent_id#' d_text='#=item.value#'/> <input type='checkbox' id_a='#= item.id #' name='c_#= item.id #' value='true' />#}else{# <div id='#=item.id#' style='display:none;' parent_id='#=item.parent_id#' d_text='#=item.value#'/> #}#",
},
dataSource: homogeneous,
dataBound: ondata,
dataTextField: "value"
});
function ondata() {
//alert("databound");
}
// function that gathers IDs of checked nodes
function checkedNodeIds(nodes, checkedNodes) {
//console.log(nodes);
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].checked) {
checkedNodes.push(nodes[i].id);
}
if (nodes[i].hasChildren) {
checkedNodeIds(nodes[i].children.view(), checkedNodes);
}
}
}
// show checked node IDs on datasource change
$("#treeview").data("kendoTreeView").dataSource.bind("change", function() {
var checkedNodes = [],
treeView = $("#treeview").data("kendoTreeView"),
message;
checkedNodeIds(treeView.dataSource.view(), checkedNodes);
if (checkedNodes.length > 0) {
message = "IDs of checked nodes: " + checkedNodes.join(",");
} else {
message = "No nodes checked.";
}
$("#result").html(message);
});
in this code i am not getting checkbox's id when it is unchecked so i have tried this
jquery code
$('input[type=checkbox]').click(function() {
if($(this).is(':checked')) {
alert('checked');
} else {
alert('not checked');
}
});
this code is only working in js fiddle but not in my case http://jsfiddle.net/NPUeL/
if i use this code then i can get the number of count but i dont know how to use it
var treeview = $("[data-role=treeview]").data("kendoTreeView");
treeview.dataSource.bind("change", function (e) {
if (e.field == "checked") {
console.log("Recorded Selected: " + $("[data-role=treeview] :checked").length);
}
});
what changed i need to do in data source so i can get id
thanks in adavance
If you want to get the id you might do:
$('input[type=checkbox]').click(function (e) {
var li = $(e.target).closest("li");
var id = $("input:hidden", li).attr("id");
var node = treeView.dataSource.get(id);
if (node.checked) {
console.log('checked');
} else {
console.log('not checked');
}
});
What I do in the event handler is:
find the closest li element that is the node of the tree that has been clicked.
the id is in an HTML input element that is hidden (this is the way that I understood that you have stored it).
Get item from dataSource using dataSource.get method.
See your code modified and running here
i made the small change and its working now
function ondata() {
$('input[type=checkbox]').click(function() {
if($(this).is(':checked')) {
alert('checked');
} else {
alert('not checked');
}
});
}

Resources