How to pass a row field value to 'enableCellEdit' attribute? - javascript

In Angular UI-Grid table, I have one date column (referenceDate) which I want to enable/disable edit based of a flag called 'allowed' which is part of the row value.
How to pass this row value in 'enableCellEdit' attribute ?
Here is my code fragment.
I tried with 'row.entity.allowed' but it did not worked. And got error
Error: row is not defined
$scope.gridOptions.columnDefs = [
{
field : "referenceDate", width : "15%", enableCellEdit: row.entity.allowed, type: 'date', cellFilter: 'date:"yyyy-MM-dd"',
},
{
field : "manuallyUpdated", width : "10%", cellEditableCondition: false, cellTemplate: '<input type="checkbox" ng-model="row.entity.manuallyUpdated" disabled="true" style="zoom:1.5" >'
}
];
JSON data
{
"referenceDate": "2015-09-30",
"allowed": true,
"manuallyUpdated": true
}

Basically, you are not able to access the external scope when setting a value for enableCellEdit.
You should make use of cellEditableCondition and pass it a function like this -
function($scope){
return $scope.row.entity.allowed;
}
From the docs :
If specified, either a value or function evaluated before editing
cell. If falsy, then editing of cell is not allowed.

Related

How to refresh ui-grid cell which has a cellFilter to display multiple fields of the bound entity in one cell

I use a cell filter to show multiple properties of a bound entity in one cell. Therefore there is no one field name because it is a computed field. How can I force the grid to reevaluate the cell filter if one of the involved properties changes?
The column definition:
columnDefs: [
{ field: 'xxx', displayName: 'Something', cellFilter: 'concatSomeProps:this' }
]
The filter:
myApp.filter('concatSomeProps', function () {
return function (cellValue, scope) {
var entity = scope.row.entity;
return entity.prop1 + ", " + entity.prop2;
};
});
If have tried to use notifyDataChanged or the refresh function of the grid api but it doesn't work.
I'd probably use a cellTemplate, and not a filter in this case:
{ field: 'xxx', displayName: 'Something', cellTemplate:'template.html' }
And
<script type="text/ng-template" id="template.html">
<div>
{{row.entity.name + row.entity.age}}
</div>
</script>
See this Plnkr I made for you to see what I'm talking about. Edit either one of the first two fields and you will see the concat field change. You'd also change your template to use row.entity.prop1 + row.entity.prop2 to make it work, as my template is for my columns.

Kendo Grid: how to get the selected item from a Combobox cell template when using with Angular

I have a Kendo grid which I am using within Angular, and have a field with a combo box, that has the editor set to the following function...
function comboCellTemplate(container, options) {
var input = $('<input name="' + options.field + '" />')
input.appendTo(container)
var combobox = input.kendoComboBox({
autoBind: true,
filter: "contains",
placeholder: "select...",
suggest: true,
dataTextField: "description",
dataValueField: "code",
dataSource: data,
});
And data is a list of simple json objects...
[
{code: 'code1', description: 'desc1'}
{code: 'code2', description: 'desc2'}
[
Each field in the grid data is bound to the same objects (ie with a code and description field)
I a previous post, to get sorting and filtering working I need to bind a field to the display field...
{
field: "Category.description",
title: "Category",
editor: comboCellTemplate,
template: "#=Category.description#"
},
When I do this, the combo box seems to set the field of the grid to the code.
How can I get this to set the grid data to the whole data object (ie the {code, description})
I have tried adding a on - change handler to do this
input.on('change', function () {
var val = input.val();
//var dataItem = input.dataItem();
options.model.set(options.field, val + 'xx');
});
but can't see how to get the "selected Item" from the combo
I don't seem to be able to find this in the help (in particular when using Angular)
Any help here would be greatly appreciated.
regards, Peter
I think you can simply add a change handler to the editor and set it from there:
function comboCellTemplate(container, options) {
var input = $('<input name="' + options.field + '" />')
input.appendTo(container)
var combobox = input.kendoComboBox({
autoBind: true,
filter: "contains",
placeholder: "select...",
suggest: true,
dataTextField: "description",
dataValueField: "code",
dataSource: data,
change: function () {
options.model.set(options.field, this.dataItem());
}
});
}
Ok, I think I have got to the bottom of this (after lots of diving through the doco)
I could get everything to work after I discovered that you can give a column a "magical" compare function.
So using this, my field can go back to binding to the whole json object ..
and add the sortable as follows...
{
field: "Category",
title: "Category",
editor: comboCellTemplate,
template: "#=Category.description#",
sortable:{
compare: function (a, b){
return a.Category.description.localeCompare(b.Category.description);
}
},
Now everything works exactly as I expect, and I don't need to do anything extra in the combobox. I hope this ("simple when you know how") tip can save someone else all the time it took me to find it.

changing data of select2 with x-editable without re-setting source option

How to keep the source of option values updated in x-editable
without re-initialising the editable element with source.
Here is the sandbox : http://jsfiddle.net/wQysh/322/
HTML
<p>X-editable (dev)</p>
<div>
<button id="controller">Add</button>
</div>
<div>
<button id="controller1">Remove</button>
</div>
<div>
<button id="controller2">Update</button>
</div>
<div style="margin: 50px">
</div>
<div style="margin: 50px">
</div>
<div style="margin: 50px">
</div>
<div style="margin: 50px">
</div>
JS :
$.fn.editable.defaults.mode = 'inline';
var count = 4, sources = [];
for(var i = 1; i <= count; i++){
sources.push({ id : i, text : String(i) })
}
var getSource = function() {
//i want this function must be called whenever available options is rendred. to ensure i used JSON.parse
return JSON.parse(JSON.stringify(sources));
};
$('#controller2').click(function(e){
count++;
sources[2].text = String(count);
//to verify live changes, if a new record updated in sources and used instantly
$('#username').editable('setValue', [1, count]); $('#username2').editable('setValue', count);
});
$('#controller').click(function(e){
count++;
sources.push( {id : count, text :String(count) });
//to verify live changes, what if a new record added in sources and used instantly
$('#username').editable('setValue', [1, count]); $('#username2').editable('setValue', count);
});
$('#controller1').click(function(e){
count++;
var a = sources.pop();
//to verify live changes by selecting value that is not present in the list. It should escape those, print the rest all if available in list
$('#username').editable('setValue', [1, a.id]); $('#username2').editable('setValue', a.id);
});
$('#username').editable({ //to keep track of selected values in multi select
type: 'select2',
url: '/post',
autotext : 'always',
value : [1,2],
source : getSource,
emptytext: 'None',
select2: {
multiple : true
}
});
$('#username2').editable({ //to keep track of selected values in single select
type: 'select2',
url: '/post',
autotext : 'always',
value : 2,
source : getSource,
emptytext: 'None',
select2: {
multiple : false
}
});
$('#username3').editable({ //to keep track of available values in multi select
type: 'select2',
url: '/post',
autotext : 'always',
value : null,
source : getSource,
emptytext: 'None',
select2: {
multiple : true
}
});
$('#username4').editable({ //to keep track of available values in single select
type: 'select2',
url: '/post',
autotext : 'always',
value : null,
source : getSource,
emptytext: 'None',
select2: {
multiple : false
}
});
//ajax emulation. Type "err" to see error message
$.mockjax({
url: '/post',
responseTime: 400,
response: function(settings) {
if(settings.data.value == 'err') {
this.status = 500;
this.responseText = 'Validation error!';
} else {
this.responseText = '';
}
}
});
Requirement :
Whenever i add new item in sources, if item is not selected then it should be updated in available options otherwise if selected then view should have updated value at element.
Whenever i update an item in sources, if item is not selected then it should be updated in available options otherwise if selected then view should have updated value at element.
Whenever i delete an item in sources, if item is not selected then it should be removed from the available options otherwise if selected then view should have "None" value (if single select) and rest element values (if multi select) at element.
Not allowed:
to reinit the widget
to reinit the source option
I hope this is possible. But struggling to get the result.
EDIT2 : code did not worked when i used JSON.parse over stringified 'sources' Problem is still unresolved. New fiddle : http://jsfiddle.net/wQysh/322/
(EDIT1 was misleading this question so removed EDIT1)
EDIT3 : so far i am able to achieve this http://jsfiddle.net/wQysh/324/
Here problem is that previous selected values are not rendered, so can't remove the items if selected previously in multi-select
EDIT4: not completely solved, http://jsfiddle.net/wQysh/339/. After add or update the available option does change but after setting that new record, does not reflect in html element after submit.
the answer is to use a custom display function
here is the updated fiddle. http://jsfiddle.net/wQysh/357/
Every time we 'setValue' to editable or on close event editable's 'display' function is called.
in display function existing values is checked by this function
$.fn.editableutils.itemsByValue
where the third parameter accepts the idKey. If we do not provide third parameter while calling this function, it by default takes 'value' as idKey. and 'value' as idKey should not be used when we are using to load array data. ref : http://ivaynberg.github.io/select2/#data_array.
I added display function in which third parameter is 'id'.
and i got the desired result

How to define a Kendo grid Column filter between two dates?

In our application we want the filter on a date column to prompt the user for a start date and an end date, with the filter returning rows where the field in question falls between (or on) those two dates.
Initial Approach
Our initial approach was to restrict date types to use gte and lte operators, and add the "extra : true" filterable option on the column. This came close, but presented the following problems: A) Each date input could use either the gte (Start) or lte (End) operator, providing undesired flexibility and the option for the user to create a filter that would never return results, and B) Presented a logical comparison (And / Or) that we don't want.
Better Approach
This question has an answer by Matthew Erwin that gets us very close: it allows us to completely re-style the filter entirely, so we can present simply a Start Date input and an End date input. However, what I can't get working is associating the right filter operation with the right input (gte for the Start date, lte for the End date). My custom filter is as follows:
$scope.dateFilter = {
extra: true,
operators: {},
ui: function (element) {
var parent = element.parent();
while (parent.children().length > 1)
$(parent.children()[0]).remove();
parent.prepend(
"Start Date:<br/><span class=\"k-widget k-datepicker k-header\">" +
"<span class=\"k-picker-wrap k-state-default\">" +
"<input data-bind=\"value: filters[0].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
" style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" aria-disabled=\"false\" " +
" aria-readonly=\"false\" aria-label=\"Choose a date\">" +
"<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
"<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>" +
"<br/>End Date:<br/>" +
"<span class=\"k-widget k-datepicker k-header\"><span class=\"k-picker-wrap k-state-default\">" +
"<input data-bind=\"value: filters[1].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
" style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" " +
" aria-disabled=\"false\" aria-readonly=\"false\" aria-label=\"Choose a date\">" +
"<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
"<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>"
);
}
};
With this approach, the Odata filter option is generated for each of the dates, however it uses the eq Equal To operator, so no values are ever returned. We aren't building filters specifically on the data source.
Is there a simple way I can associate each of those date inputs with a specific filter operator? Is there a better way to approach this subject? It seems like filtering dates based on a Start - End range would be commonly desired.
Other Details
We are using AngularJS, and WebAPI with Odata.
After working with Telerik, I came to an answer. The thread that I opened can be found here, but I'll also summarize in this answer.
The ultimate solution was to:
Use the "Messages" option of the column "filterable" option to customize the filter display message.
Use the "Extra" option of the column "filterable" option to get the extra Date selector in the filter menu.
Configure the "Operators" option in the grid filterable option to set what operators can be used for dates (gte, lte) and what text is displayed for each (Begin Date, End Date).
Use the filterMenuInit event to configure the filter controls.
End Result
Column Filterable
The following filterable options were used:
filterable: { "extra": "true", "messages": { "info": "Show items between dates:" }}
Extra gives us the second date selector, and the "info" message customizes the text displayed at the top of the filter menu.
Grid Filterable
I used the "operators" option in the grid-level "filterable" option to make date filters only provide the gte and lte operators, and to customize the text for those operators. This is what the operators configuration object wound up looking like:
"date": {
"gte": "Begin Date",
"lte": "End Date"
}
Because we want this to apply for all dates, we put that in a factory and reuse it in each angular controller / view.
filterMenuInit Event
By providing a handler for the filterMenuInit event, you can access and configure the individual controls in the filter menu as it is created. The handler function that I created looks like this:
function (e) {
if (e.sender.dataSource.options.schema.model.fields[e.field].type == "date") {
var beginOperator = e.container.find("[data-role=dropdownlist]:eq(0)").data("kendoDropDownList");
beginOperator.value("gte");
beginOperator.trigger("change");
beginOperator.readonly();
var logicOperator = e.container.find("[data-role=dropdownlist]:eq(1)").data("kendoDropDownList");
logicOperator.readonly();
var endOperator = e.container.find("[data-role=dropdownlist]:eq(2)").data("kendoDropDownList");
endOperator.value("lte");
endOperator.trigger("change");
beginOperator.readonly();
}
Specifically, for any date field, this function sets the first and last dropdown operators to "gte" and "lte" respectfully (Those are the dropdowns for the first date operator and the second date operator), and sets all of the dropdowns to read-only so the user can't change them (the only other dropdown, which is at index 1, is the logical comparison - only And makes sense, so we don't let users change it.)
This function applies this configuration for any fields that are of "date" type. I did it this way so that I could create this function once, put it in an Angular factory, and then reuse it for any grid that I needed. If you don't want to apply this as a blanket configuration across all of your date columns, you can change the conditional to check for fields by name. Example:
if (e.field == "fieldName")
Hopefully this will be helpful to someone else. This doesn't give you ultimate customization of the UI in the filter menu, but it does let you simply set up a filter between two dates. I'm sure someone clever could merge this with my original strategy (replacing the markup for the filter menu entirely) to come up with something completely customized.
You can try the following method that gives two option for filtering: With two filtering fields and with the grid column.
<div>
From: <input id="from" /> To: <input id="to" />
<br />
<br />
<button id="filter" class="k-button">Filter</button>
</div>
<br />
<br />
<div id="grid"></div>
<script>
var grid = $("#grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: "/Controller/Action"
},
pageSize: 10,
schema: {
model: {
fields: {
OrderId: { type: 'number' },
OrderItem: { type: 'string' },
OrderDate: { type: 'date' }
}
}
}
},
pageable: true,
filterable: true,
navigatable: true,
selectable: true,
columns:
[
{ field: "OrderID", width: 100, title: "Order ID", filterable: false },
{ field: "OrderItem", width: 100, title: "Order Item", filterable: false },
{
field: "OrderDate", type: "date", width: 125, title: "Order Date",
template: "#= kendo.toString(kendo.parseDate(EventTime, 'dd.MM.yyyy hh:mm tt'), 'dd.MM.yyyy hh:mm tt') #",
filterable: {
ui: "datetimepicker"
}
},
]
}).data("kendoGrid");
$("#from, #to").kendoDatePicker({
});
$("#filter").on("click", function () {
//var from = $("#from").data("kendoDatePicker").value();
//var to = $("#to").data("kendoDatePicker").value();
//If there is a problem regarding to the two lines above, you can also try this:
var from = $("#from").val();
var to = $("#to").val();
var filter = [
{ field: "OrderDate", operator: "gte", value: from },
{ field: "OrderDate", operator: "lte", value: to }
];
grid.dataSource.filter(filter);
});
</script>
For more information Date Range Filtering in Kendo Grid Using WEB API and Entity Framework.

Showing serial number in jqgrid

I want to show serial number as first column in jqgrid.since, database records doesn't has contigous 'ids', I can't use it.
Is there any simple way to accomplish this?
Update:
sample code:
$(document).ready(function()
{
$("#list").jqGrid(
{
url:'<%=Url.class_variable_get(:##baseurl) %>/address_books/show.json',
datatype:'json',
mtype:'get',
colNames:['Id','Name','Email Id','Number'],
colModel:[
{name:'address_book_id',index:'address_book_id',sorttype:'int',sortable:true,width:100},
{name:'name',index:'name',sortable:true,width:300},
{name:'email',index:'email',sortable:true,width:265},
{name:'number',index:'number',sorttype:'int',sortable:true,width:300},
],
pager:$('#pager'),
emptyrecords: "No Records to display",
pginput:true,
pgbuttons:true,
rowNum:10,
rowList:[5,10,20,30],
viewrecords:true,
sortorder: "desc",
//multiselect:true,
loadonce:true,
gridview:false,
sortname:'name',
caption: " Contacts List",
jsonReader: {
repeatitems : false,
cell:"",
id: "0"
},
height: 80
});
$("#list").jqGrid('navGrid','#pager',{edit:false,add:false,del:false,search:true},{multipleSearch:true});
});
This question/answer should contain information on how to redraw the jqgrid based on redefined table data: jqGrid add new column
Regarding the addition of a you might add a time stamp to each of the records, or even the value of a counter; something like:
var recordsSet = [];
$.each(databaseRecords, function(i, record) {
record.idx = Date.now();
record._id = i;
recordSet.push(record);
});
/* code to populate or redraw using update recordSet array jqgrid here */
You shoud then be able to assign either the _id field or the idx field (sample property names only) to the index property of your column models in the call to jqgrid.

Categories

Resources