I have Angular UI Grid where a user can change sorting order by clicking on column headers. I want to preserve user’s choice when the user leaves the controller and restore chosen sorting order when the user returns to the controller. UI Grid has saveState module so I am using it to save the state when the uses leaves the controller.
The issue is that I can’t restore this saved state. When should I call saveState.restore()? If I call it in onRegisterApi then it doesn’t work since columns aren’t constructed yet.
You can try this way
$scope.gridOptions = {
exporterMenuCsv: false,
enableGridMenu: true,
enableColumnResizing: true,
enableFiltering: true,
saveVisible: true,
saveOrder: true,
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
$timeout(function () {
$scope.restoreState(); //call my restore function
}, 100);
},
data: $scope.bookings
};
I call it just after I have filled the grid with data.
$scope.loadData = function () {
$q.all([
myDataLoaderFunction.$promise
])
.then(function (data) {
$scope.gridOptions.data = data[0];
var savedState = SomeServiceThatIStoredMyStateInto.getSavedGridState();
if (savedState) {
$scope.gridApi.saveState.restore($scope, savedState);
}
}, function () {
$scope.gridOptions.data = [];
});
};
Related
I have a grid that contains an edit button per each row. Everything works as expected the first time the page is loaded, but if I try to add a new entity and repopulate the grid, the edit button will fire the edit event of the first already existing entity.
This is my code:
var columnDefs = [
{
name: '', field: 'id',
cellTooltip: 'Edit',
enableSorting: false,
enableColumnMenu: false,
enableCellEdit: false,
maxWidth: 30,
headerCellTemplate: '<div class="ui-grid-cell-contents ui-grid-icon"></div>',
cellEditableCondition: false,
cellTemplate: '<div class="ui-grid-cell-contents ui-grid-icon"><div title="Edit" class="ui-edit ui-grid-icon-pencil" ng-click="grid.appScope.editNews({{row.entity.id}})"></div></div>'
},
{ name: 'shortDescription', field: 'shortDescription' }];
$scope.gridOptions = {
enableGridMenu: false,
enableSorting: false,
enableRowHashing: false,
columnDefs: columnDefs,
data: "data",
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
}
};
var getData = function () {
showLoading('.grid');
newsRepository.resourceFunctions.query(displayOptions,
function (data) {
if (data.length == 0) {
setEmptyGrid($scope, 'There are no news!');
$scope.data = [{
"message": 'There are no news!'
}];
}
else {
setGrid(data);
}
hideLoading('.grid');
}, //success
function (error) {
$scope.gridApi.selection.clearSelectedRows();
hideLoading("#view-container");
toaster.pop('error', "Server error",
"There was an error while processing your request. Please contact support.", 10000);
}); //error
};
function setGrid(data) {
$scope.gridOptions.columnDefs = columnDefs;
$scope.data = data;
}
This is how the grid is re-populated (the data is comming from the save AJAX request):
$scope.gridApi.selection.clearSelectedRows();
setGrid(data.items);
The edit event is inside the cellTemplate: grid.appScope.editNews({{row.entity.id}}). Also, after the grid data is updated, this template is populated with the correct entity id, but the editNews is called with the id of the older entity. Any ideas how I can fix this?
I had a similar problem to this today, although more to do with cellTemplate buttons not shifting to their correct row when a new row was added, or an existing row removed.
In your particular case just remove the {{ and }} in your call to editNews. E.g. it should be:
ng-click="grid.appScope.editNews(row.entity.id)". This worked nicely for me.
This is my first post. stackoverflow is a wonderful place for developers. Here is my issue.
I am trying to use Autocomplete in JqGrid Edit Form. i successfully retrieved data from server using ajax call but dont know how to display it in the view. below is my code.
FrontEnd Code:
colModel :[
{name:'prf_articlename', index:'prf_articlename', width:90, editable:true, edittype:'text',
editoptions: {
dataInit:function(e){
$(e).autocomplete({
source: function(request, response,term) {
var param = request.term;
$.ajax({
url: '/Myelclass/AutoCompleteServlet.do?term='+param+"&action="+"artname",
success: function (data) {
response($.map(data, function(item) {
return {
label: item.label,
};
}));//END Success
},
});//END AJAX
},
minLength: 2,
});//END AUOTOCOMPLETE
}//END Dataint
}//END Dataint
},
BackEnd Code:
String term = request.getParameter("term");
List<AutoComplete> articlelist = prfbo.getArticleNameinEditGrid(term);
System.out.println("List Value " +articlelist.size());
JSONArray jsonOrdertanArray = JSONArray.fromObject(articlelist);
System.out.println(jsonOrdertanArray);
out.println(jsonOrdertanArray);
Any one help on this???
This is what I personally use in my project:
Inside colModel:
dataInit: function (elem) { NameSearch(elem) }},
The function:
function NameSearch(elem) {
$(elem).autocomplete({ source: '/Controller/NameSearch',
minLength: 2, autosearch: true,
select: function (event, ui) {
$(elem).val(ui.item.value);
$(elem).focus().trigger({ type: 'keypress', charCode: 13 });
}
})//$(elem).autocomplete
$(elem).keypress(function (e) {
if (!e) e = window.event;
if (e.keyCode == '13') {
setTimeout(function () { $(elem).autocomplete('close'); }, 500);
return false;
}
})//$(elem).keypress(function (e){
} //function NameSearch(elem) {
I'm also dealing with an Enter key press as well in the above function.
here is the complete code for my Autocomplete in jqgrid Edit form..
colModel :[
{name:'name', index:'name', width:90, align:'center', editable:true, hidden: false, edittype:'text',
editoptions:{
dataInit:function (elem) {
$(elem).autocomplete({
minLength: 2,
source: function(request, response,term) {
var param = request.term; //values we enter to filter autocomplete
$.ajax({
url: "myurl",
dataType: "json",
type:"GET",
success: function (data) {
response($.map(data, function(item) {
return {
//can add number of attributes here
id: item.id,
shform: item.shortform,
value: item.name,
clr : item.color, //here apart from name and id i am adding other values too
size: item.size,
remar:item.remarks,
subs: item.subs,
selec:item.selec ,
};
}));//END Response
},//END Success
});//END AJAX
},
select: function( event, ui ) {
// setting values to textbox in jqgrid edit form based on selected values
$('#textbox1').val(ui.item.id);
$('#textbox2').val(ui.item.shform);
$('#textbox3').val(ui.item.clr);
$('#textbox4').val(ui.item.size);
$('#textbox5').val(ui.item.sizeremar);
$('#textbox6').val(ui.item.subs);
$('#textbox7').val(ui.item.selec);
$('#textbox8').val(ui.item.selp);
}
});
$('.ui-autocomplete').css('zIndex',1000); // if autocomplete has misalignment so we are manually setting it
}
}, editrules :{required : true},
formoptions:{rowpos: 1, colpos: 2}
},
........
]
server code :
String term = request.getParameter("term");
List<ArticleDetails> articlelist = prfbo.getPrfArticleName(term); //DB call via BO and DAO class
System.out.println("List Value " +articlelist.size());
JSONArray jsonOrdertanArray = JSONArray.fromObject(articlelist);
System.out.println(jsonOrdertanArray);
out.println(jsonOrdertanArray);
hope some one find it useful.
I have two views in database. Bonuses and employees. One(employee)-to-many(bonuses).
I have kendo ui grid (kendo web), which displays ajax results from controller called Bonuses
And an autocompliting element - Employee Combobox binded with Employee filed of a grid.
Grid's datasource:
// bind json result from /Bonuses/GetPagedJsonBonuses
var bonusesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetPagedJsonBonuses", "Bonuses")",
update: {
url: "#Url.Action("Edit", "Bonuses")",
type: "PUT"
},
create: {
url: "#Url.Action("Create", "Bonuses")",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
// updates the BonusDTO.EmployeeId with selected value
if (newValueEmployeeId !== undefined)
options.EmployeeId = newValueEmployeeId;
}
return options;
}
},
schema: {
data: "Data", // PagedResponse.Data
total: "TotalCount", // PagedResponse.TotalCount
model: {
id: "BonusId", // Data
fields: {
EmployeeId: { type: "number" },
EmployeeLastName: {
type: "string",
editable: true,
//validation: { required: {message: "Employee's last name is required"}}
},
Amount: {
type: "number",
editable: true,
nullable: false,
validation: {
required: { message: "Amount is required to be set" }
}
}
} // fields
} // model
}// schema
});
Grid element looks like this:
// creates bonuses grid control
$("#bonusesGrid").kendoGrid({
dataSource: bonusesDataSource,
toolbar: ["create"],
editable: "inline",
columns: [
"BonusId",
"EmployeeId",
{
field: "EmployeeLastName",
editor: employeeAutocompletingEditor,
template: "#=EmployeeLastName#"
},
"Amount",
{
command: ["edit"],
title: " "
}
],
save: function(e) {
if (newValueEmployeeId !== undefined && newValueEmployeeLastName !== undefined) {
e.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
e.model.EmployeeLastName = newValueEmployeeLastName;
}
},
edit: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
},
cancel: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
}
});
Autocompleting combobox has it's own datasource using ajax:
// datasource for autocomlete combobox to lookup employees names from
var employeesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetJsonEmployeesByLastName", "Bonuses")",
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
setNewValueEmployeeIdAndLastName(options.Id, options.LastName);
}
return options;
},
});
Autocompliting combobox look's like this:
function employeeAutocompletingEditor(container, options) {
$('<input required data-text-field="LastName" data-value-field="EmployeeId" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
// sets the local variables to update values of current row.
change: function() {
setNewValueEmployeeIdAndLastName(this.value(), this.text());
},
dataBinding: function (e) {
console.log("dataBinding: ", e, this.dataItem());
},
dataBound: function (e) {
console.log("dataBound: ", e, this.dataItem());
},
dataSource: employeesDataSource
});
}
I use Editor binding to pass values(EmployeeId) and Text (EmployeeLastName) from grid to combobox.
I also use a hack like temporal variables (newValueEmployeeId, currentValueEmployeeId) to
send selected Employee in combobox and pass it to grid for correct save. A found it's a most common practice to pass a value back to grid.
My problems is:
If I press Edit button on my grid first time The combobox displays current employee's name from grid row:
If I press Cancel button and again press Edit button, combobox doesn't display current value of grid (employee's name)
IF I type some name, change some other values, and Udate(save) value, next time combobox again displays employees name, but only once before Cancel was pressed.
I'm very new in Kendo UI and this problem drives me crazy...
I think that combobox losts it's binding or doesn't update smth. I tried to set values while onBound and onBinding events, but this doesn't help. Please help me with an advice and example.
PS all evenets and functions is my try to debug and find solution.
only one fix helped me:
var employeeList = new List<Employee>()
employeeList.add(new Emplpyee()) // add fake employee record.
return Json(employeeList)
I don't know why, but grid control start make cyclying empty ajax requests if I return empty list of employees or null. This doesn't work:
return Json(new List<Employee>());
return Json(null);
I think it's a problem in kendo combobox itself ,because it's not ready to receive and handle empty list or null as json result.
Also I heared something, that JQuery doesn't support empty or null results anymore...maybe that's the reason
I'm using jquery-ui autocomplete on a page I'm creating. On the same page I have some ajax events going on. During the other ajax events I'm adding an overlay to my page, so that all the links on the website aren't clickable anymore for the user. I don't want that to happen during the autocomplete.
autocomplete:
$(function() {
$( "#search_input" ).autocomplete({
source: '/search_autocomplete/',});
});
ajax:
$.ajax({
url: "/ajax_login/",
login_user: $("#login_user").val(),
password: $("#login_password").val(),
});
ajaxStart:
$("#loading_gif").ajaxStart(function() {
$("#overlay").show();
$(this).show();
});
To prevent the ajaxstart function from being executed during the ajax events where it's not necessary. I add
global:false,
to the corresponding ajaxfunctions. How can I do something similar during the autocomplete without changing the jquery-ui source?
For this you have to omit the shorthand call with source and change the call like this.
$('#search_input').autocomplete({
source: function (request, response) {
var DTO = { "term": request.term };
//var DTO = { "term": $('#search_input').val() };
$.ajax({
data: DTO,
global: false,
type: 'GET',
url: '/search_autocomplete/',
success: function (jobNumbers) {
//var formattedNumbers = $.map(jobNumbersObject, function (item) {
// return {
// label: item.JobName,
// value: item.JobID
// }
//});
return response(jobNumbers);
}
});
}
//source: '/search_autocomplete/'
});
The advantage of this long-hand method is
You can pass more than one parameter. Also the parameter name should not have to be term.
The short-hand notation expects an array of strings. Here you could return an array of objects also.
If you want $.ajax() to work a certain way most of the time but now all the time, then you probably shouldn't change its default behavior.
I recommend creating a function that wraps an ajax request in a function that enables and disables the overlay at the appropriate times. Call this function where you want the overlay to be used, and use plain $.ajax() for your autocomplete.
I would agree that naveen's answer is the best solution. In my case the vast amount of code that would require changing wasn't cost effective as we're in the process of doing a re-write and we needed a short term solution.
You can override the ajax call in jQuery UI, I copied the source for the _initSource function call that handles the AJAX request. Then simply added the global: false to the $.ajax options. The code here is based on jquery-ui 1.9.2, you may have to find the correct source for your version.
$.ui.autocomplete.prototype._initSource = function () {
var array, url,
that = this;
if ( $.isArray(this.options.source) ) {
array = this.options.source;
this.source = function( request, response ) {
response( $.ui.autocomplete.filter( array, request.term ) );
};
} else if ( typeof this.options.source === "string" ) {
url = this.options.source;
this.source = function( request, response ) {
if ( that.xhr ) {
that.xhr.abort();
}
that.xhr = $.ajax({
url: url,
data: request,
dataType: "json",
global: false,
success: function( data ) {
response( data );
},
error: function() {
response( [] );
}
});
};
} else {
this.source = this.options.source;
}
};
I have written a code to integrate timepicker with editable which is being used to make all coulmns except the hidden id coulmn and the first shown coulmn editable . I couldn't get the fnupdate make my edited coulmn to be updated to the new value when it is posted to server side . I am able to get the posted values for server side processing but the clientside is not gettting updated by fnupdate .
Please see the code below and try to tell me what i am doing wrong because i am having many pages which function the same way .
$(document).ready(function() {
oTable = $('#scheduleTable').dataTable(
{
"sDom" : '<"top"flip>rt<"bottom"<"clear">',
"bAutoWidth" : false,
"bProcessing" : true,
bJQueryUI:true,
"bServerSide": true,
"bFilter":false,
"bSort": false,
"bInfo": false,
"bPaginate":false,
"aoColumns":[
{
"bVisible" : false
},
{
},
{},
{},
{},
{}
],
"fnRowCallback" : function (nRow, aData, iDisplayIndex) {
$(nRow).attr('id', '' + aData[0]);
//i starting from one to make the first element in td non editable
for (i = 1; i < aData.length; i ++) {
$('td:eq(' + i + ') ', nRow).editable("<?= $aupdateUrl; ?>", {
'callback': function (sValue, y) {
var aPos = oTable.fnGetPosition(this);
oTable.fnUpdate(sValue, aPos[0], aPos[1]);
},
"submitdata": function ( value, settings ) {
return {
"row_id": this.parentNode.getAttribute('id'),
"column": oTable.fnGetPosition( this )[2]
};
},
'height': '14px',
indicator : 'Saving...',
tooltip : 'Doubleclick to edit...',
type : "timepicker",
placeholder : ' '
});
}
return nRow;
},
"sAjaxSource" : "<?= $aSourceList; ?>/startdate/<?= $this->startdate; ?>"
}
);
});
$('.ui-datepicker-close').live('click', function (e){
e.preventDefault();
$('#scheduleTable tbody td input').parents("form").submit();
});
$.editable.addInputType('timepicker',{
/*create input element*/
element:function(settings,orginal){
var form = $(this),
input = $('<input type="text">');
form.append(input);
return (input);
},
plugin:function(settings,original){
/*Don't cancel inline editing onblur to allow clicking datepicker*/
settings.onblur = 'nothing';
$("input",this).filter(":text").timepicker(
{ timeFormat: 'hh:mm',
'hourMin':6,
'hourMax':21,
'showSecond': false,
'hourGrid':2,
'minuteGrid':10
}
);
}
});
I was able to solve the problem .The main thing that i was doing wrong was that i didn't have json response with only one value from my server side zend framework action.Therefore it caused the editable to function in a way that it couldn't put the value(the response) as the new value in the td element. Hope some on find it usefull peace!!