I did successfully add a row double click event listener to my grid by:
listeners : {
itemdblclick: function(dv, record, item, index, e) {
alert('working');
}
},
Now, I need to get the exact value in third column at the selected row, how can I do that ?
EDIT
Okay found it:
listeners: {
itemclick: function(dv, record, item, index, e) {
alert(record.get('name'));
}
}
but seems like the result of record.get('name') is not a text! its an object but I cannot handle it as if it a text. any body has any idea ?
EDIT
For example, if I pass the name to search function: Search(record.get('name')); this won't work. but if I pass it this way: Search('Mike'); it works !
Ensure that
Your property name is really lowercase 'name' and not 'Name'
Print the value of the field into the console with console.log(record.get('name')) or use the direct access by typing console.log(record.data.name) or console.log(record.data['name']). Basically all should return the same.
To cast a value to string apply '' on the fly like var myVar = 2; myVar = myVar + ''; // now print 20 as string
Try with,
listeners: {
itemclick: function(dv, record, item, index, e) {
var selectedRec = dv.getSelectionModel().getSelected();
alert(selectedRec.get('name')); //Will display text of name column of selected record
}
Related
In my app, I need to show the index of the data entry in the first datatable column and it must work after DnD (so I suppose the column should be dynamically refreshed). But how is it possible in Webix datatable?
For now, I am able to get the index manually using getIndexById, but this method doesn't work in the column template. For instance:
/* inside the config */
drag:true,
columns:[
{ id:"index", template:function(obj){
console.log(obj.id);
// doesn't work:
// console.log(datatable.getIdByIndex(obj.id));
} },
{ id:"id" },
{
id:"title", fillspace:true, sort:"string"
}
],
ready:function(){
this.eachRow(
function (row){
console.log( this.getIndexById(row) ) // works
}
)
}
});
/* somewhere else */
console.log(datatable.getIdByIndex(4));
Code sample.
Is this possible at all? Thanks.
To get the index of row (data entry) you must define your index template as:
template: function(obj){
return $$("dt").getIndexById(obj.id); }
where "dt" is the id of your datatable. It automatically changes the index when you perform any DnD operation. Further, check the snippet here.
I have a sap.m.Input with a regex binding. When my input is "A", "B" or "C" my text is black, otherwise it becomes red through CSS.
oComponent.attachValidationError(function(oEvent) {
oEvent.getParameter("element").addStyleClass("become-red");
});
oComponent.attachValidationSuccess(function(oEvent) {
oEvent.getParameter("element").removeStyleClass("become-red");
});
var oInput = new sap.m.Input( {
value: {
path: "Qux>/foo/0/bar/0/baz",
type: new sap.ui.model.type.String(null, {
search: new RegExp("^[ABC]$")
})
}
});
When the value is "A" and I change it to "B", this works properly.
Then, if I do
oModelQux.setProperty("/foo/0/bar", [{
"baz" : "A"}]);
This works properly, the value becomes "A" again. My problem is that when I change the value of the input to a value which is not alllowed (e.g. "D"), and then I try my code
oModelQux.setProperty("/foo/0/bar", [{
"baz" : "A"}]);
nothing happens. The input does automatically update to "A", it just leaves the string "D" in red.
The binding should avoid that wrong values are stored in the model. If you change the value from "A" to "D" the value is never stored in the model, i.e. the model holds still "A". Thus your call to setProperty has no effect, as the internal value of the binding has never changed and setProperty does not force bindings to update in case of unchanged data.
I suggest that you obtain the binding of the input field if the button is clicked and call refresh(true). This should work (not tested).
Beside that I would suggest to use a Select control as it looks like that the available values are fixed. This would make the special logic obsolete.
Based on matbtt's answer, the following solution works without sacrifing performance:
undo for a single entry ('foo' level) triggers the following event:
oEventBus.publish("undo", "undoAll", oContext.getPath());
undo for all lines triggers the following event:
oEventBus.publish("undo", "undoAll");
attaching the following change function to each input:
var oInput = new sap.m.Input( {
value: {
path: "Qux>/foo/0/bar/0/baz",
type: new sap.ui.model.type.String(null, {
search: new RegExp("^[ABC]$")
}),
change: function(oEvent){
var that = this;
var oRegex = new RegExp("^[ABC]$");
var bTest = oRegex.test(oEvent.getParameters().newValue);
if (!bTest) {
var fnSubscribe = function(sChannelId, sEventId, oData) {
if (!oData || oData === oContext.getPath()) {
that.mBindingInfos.value.binding.refresh(true);
that.removeStyleClass("invalid-value");
oComponent.getEventBus().unsubscribe("undo", "undoAll", fnSubscribe);
}
};
oComponent.getEventBus().subscribe("undo", "undoAll", fnSubscribe);
}
}
}
});
I am implementing Devexpress Grid Control in MVC. I was stuck at a point where i need the current Sorted By column and Sort Order (asc/desc) in javascript. I also tried the clientSide Event OnColumnSortingChanged(s , e) , it is only providing the name of the column at click event not from the gridview javascript object.
Got the answer after research...
Have to add CustomJsProperty to the control in the partial view as below
settings.CustomJSProperties = (s, e) =>
{
var Grid = s as MVCxGridView;
var result = new System.Collections.Hashtable();
foreach (var col in Grid.AllColumns)
{
var dataCol = col as GridViewDataColumn;
if (dataCol != null)
{
if (dataCol.SortIndex == 0)
{
e.Properties["cpColumnsProp"] = new Dictionary<string, object>()
{
{ "sortcolumn", dataCol.FieldName },
{ "sortorder", ((Convert.ToString(dataCol.SortOrder).Equals("Ascending")) ? "asc" : "desc")}
};
}
}
}
};
Handle the ColumnSortingChange event as follows
function gvChartList_OnColumnSortingChanged(s, e) {
$("#hdsortname").val(e.column.fieldName); // contains the sort column name
$("#hdsortorder").val(((s.cpColumnsProp.sortcolumn == e.column.fieldName) ? "desc" : "asc")); // contains the sort column order
}
Last but not the least, One must have to define the default sort index and sort order for the column
settings.Columns.Add(col =>
{
// column details
col.SortIndex = 0;
col.SortAscending();
});
I recently needed similar, where I wanted to save the column order, sort order, and filter information; such that a user could create saved views of a grid, and not have to keep re-entering all these preferences.
I found that in an event CustomJSPropeties I could interact with a sender being an ASPxGridView, such that I could grab a needed value from ASPxGridView.SaveClientLayout(). Also useful here can be the FilterExpression, and the VisibileRowCount - if you want to use the filter expression for exporting, but only when the VisibleRowCount is less than a certain threshold (this is the number of rows shown in the bottom pager area)
settings.CustomJSProperties = (s, e) =>
{
ASPxGridView gridView = (ASPxGridView)s;
e.Properties["cpGridFilterExpression"] = gridView.FilterExpression; //Make Filter Expressions Availabe to JavaScript
e.Properties["cpVisibleRowCount"] = gridView.VisibleRowCount; //Make Visible Row Count Availabe to JavaScript
e.Properties["cpLayout"] = gridView.SaveClientLayout(); //Get Layout String and make it available to JavaScript
};
So what does this do? Properties defined in this event are available as properties of the javascript grid view object. So here we grab these values when we can, and place them in a place where we normally cannot access them.
And then, right from JavaScript we can now access GridView.cpLayout (where GridView is the name/id supplied to your grid.)
<script type="text/javascript">
$(document).ready(function () {
$('#saveButton').click(
function () {
var layout = GridView.cpLayout;
//Perform Save...
}
);
});
</script>
To be clear, this "layout" contains sort order, visible column info, and filter information.
Layout:
https://documentation.devexpress.com/#AspNet/CustomDocument4342
https://documentation.devexpress.com/#AspNet/DevExpressWebASPxGridViewASPxGridView_SaveClientLayouttopic
CustomJSProperties:
https://documentation.devexpress.com/#AspNet/DevExpressWebMvcGridViewSettings_CustomJSPropertiestopic
Note: I add this solution here because this is what I found when I was searching for my issue. As one can see, these are similar topics of accessing the AspxGridView (base of) or MVCGridView within a CustomJSProperties event handler.
I am currently using a predefined javascript Select2.js.
Now my issue is that I have some set of values that are to be removed from the list which are again dynamic values as in say when I am editing a page and I need the already saved values again fetched from backend during page load to not appear when I am searching for the data.
For the above I need a way to access the select2 object being created on the page load and set add these values in some attribute but from a different js file.
Can anyone please help me with the same? I hope whatever I am making sense...
Thanks in advance.
Sample code --
var val = this.getVal(),
choices = this.results.find(".select2-result"),
compound = this.results.find(".select2-result-with-children"),
self = this;
choices.each2(function (i, choice) {
var id = self.id(choice.data("select2-data"));
if (indexOf(id, val) >= 0) {
choice.addClass("select2-selected");
// mark all children of the selected parent as selected
choice.find(".select2-result-selectable").addClass("select2-selected");
}
});
compound.each2(function(i, choice) {
// hide an optgroup if it doesnt have any selectable children
if (!choice.is('.select2-result-selectable')
&& choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) {
choice.addClass("select2-selected");
}
});
The above is a snippet from the select2.js..
Here this refers to the select2 object being created using the below code :
$(".select2Search").select2({
closeOnSelect: false,
width: '450px',
minimumInputLength: 3,
ajax: {},
allowClear: true,
tags: true
});
When alerted, val returns the comma separated ids of the elements already selected so I need to make sure that this.getVal() has the predefined data...
There is a function named setVal as below -
setVal: function (val) {
var unique;
if (this.select) {
this.select.val(val);
} else {
unique = [];
// filter out duplicates
$(val).each(function () {
if (indexOf(this, unique) < 0) unique.push(this);
});
this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator));
alert(this.opts.element.val());
}
}
I have two select boxes in a dialog..I was wondering if i can set the contents of the second select box based on the selection of the first box..i.e if select box1 has x selected, then select box2 contents are a, b, c..if select box1 has y selected, then select box2 contents are d, e, f.. Is this possible to implement?
Thanks
I'm guessing that the dialog with two select boxes you mentioned is part of a custom plugin you are creating. So my answer shows code you could use in the dialog file that's being created as part of the plugin.
The onChange function of Selector One creates a reference to Selector Two using:
dialog.getContentElement( 'general', 'selectorTwo' )
'general' is the id of the dialog panel containing the selectors.
'selectorTwo' is the id of the second selector.
I modified the source code from the SimpleLink tutorial hosted at cksource.com:
Creating a CKEditor Plugin with a Custom Dialog Window
http://docs.cksource.com/CKEditor_3.x/Tutorials/SimpleLink_Plugin_Part_1
Download the SimpleLink source code here:
http://docs.cksource.com/images/a/a8/SimpleLink.zip
Unzip and add the simpleLink folder to your ckeditor/plugins directory.
Update your config file by adding the simpleLink plugin to your extraplugins list:
config.extraPlugins = 'onchange,insertsnippet,resconfinearea,resiframe,simpleLink',
Or when you do CKEDITOR.replace use:
extraPlugins : 'onchange,insertsnippet,resconfinearea,resiframe,simpleLink',
Also add the button to your toolbar - 'SimpleLink'
You're going to insert the code snippet from the bottom of this message into the ckeditor/plugins/simpleLink/plugin.js file.
To make the insertion point easy to locate, the first twelve lines of the snippet overlap with lines ( 111 - 122 ) of the simpleLink/plugin.js file.
After you insert the snippet, open ckeditor/_source/plugins/forms/dialogs/select.js.
Copy the following three functions from the top of the select.js file and add them at the top of the simpleLink/plugin.js file:
addOption()
removeAllOptions()
getSelect()
Open a page that's using CKEditor and click on the SimpleLink button you added, you'll see selectors one and two at the bottom of the dialog window. When you change selector one, selector two will be updated. You should be able to modify the code to suit your application.
These pages have some useful information you can refer to when reviewing the code I posted:
Creating a CKEditor Plugin with a Custom Dialog Window
http://docs.cksource.com/CKEditor_3.x/Tutorials/SimpleLink_Plugin_Part_1
Class CKEDITOR.dialog
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.html
Class CKEDITOR.dialog.definition
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.definition.html
Here's the code snippet to insert into the ckeditor/plugins/simpleLink/plugin.js file.
Just select lines ( 111 - 122 ) and paste this in:
{
type : 'checkbox',
id : 'newPage',
label : 'Opens in a new page',
// Default value.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.checkbox.html#constructor
'default' : true,
commit : function( data )
{
data.newPage = this.getValue();
}
},
{
type : 'select',
id : 'selectorOne',
label : 'Selector One',
items :
[
[ '<none>', '' ],
[ 'Set 1', 1],
[ 'Set 2', 2 ],
[ 'Set 3', 3 ]
],
onChange : function()
{
var dialog = this.getDialog(),
values = dialog.getContentElement( 'general', 'selectorTwo' ), // 'general' is the id of the dialog panel.
selectedSet = parseInt(this.getValue());
switch(selectedSet)
{
case 1:
optionsNames = new Array("Set One <none>","Set One A","Set One B","Set One C"),
optionsValues = new Array("","setOneA","setOneB","setOneC");
break;
case 2:
optionsNames = new Array("Set Two <none>","Set Two A","Set Two B","Set Two C"),
optionsValues = new Array("","setTwoA","setTwoB","setTwoC");
break;
case 3:
optionsNames = new Array("Set Three <none>","Set Three A","Set Three B","Set Three C"),
optionsValues = new Array("","setThreeA","setThreeB","setThreeC");
break;
default:
optionsNames = new Array("<none>"),
optionsValues = new Array("");
}
removeAllOptions( values );
for ( var i = 0 ; i < optionsNames.length ; i++ )
{
var oOption = addOption( values, optionsNames[ i ],
optionsValues[ i ], dialog.getParentEditor().document );
if ( i == 0 )
{
oOption.setAttribute( 'selected', 'selected' );
oOption.selected = true;
}
}
},
commit : function( data )
{
data.selectorOne = this.getValue();
}
},
{
type : 'select',
id : 'selectorTwo',
label : 'Selector Two',
items :
[
[ '<none>', '' ]
],
commit : function( data )
{
data.selectorTwo = this.getValue();
}
},
Hope this does the trick, let me know if something isn't clear,
Joe
Hi oggiemc,
Good to know that you've had a chance to experiment with the code and it's great that it's been helpful.
Answers to the additional questions about the functions copied from the plugins/forms/dialogs/select.js file.
1) The three functions shouldn't be called when the dialog is opened. That's not occurring in the sample I created as outlined in my initial answer. You might want to search your code for the three function names to see if they are being called someplace other than the ( onChange : function() ) contained in the selectorOne definition.
2) I broke down the ( removeAllOptions() function ) and included it below. It has a similar line of code. For the line you asked about:
if (combo && oOption && oOption.getName() == 'option'),
It says If ( combo exists ) AND ( oOption exists ) AND ( oOption.getName() == 'option' ) the If statement is true.
By "exists", I mean it's not null and not something that evaluates to false (either 0 or a binary Not true).
3) Yes, in this particular usage of the addOption() function, the index variable isn't used. You can remove the two if statements and just leave the code statement from each else clause.
4) obj.getInputElement() returns the DOM element object, but obj.getInputElement().$ only returns the HTML tag for the DOM object. Try adding some console.log calls to the getSelect() function and you'll see the difference:
if ( obj && obj.domId && obj.getInputElement().$ ) { // Dialog element.
console.log(obj.getInputElement().$); // ADDED CONSOLE.LOG
console.log(obj.getInputElement()); // ADDED CONSOLE.LOG
return obj.getInputElement();
Here is the flow for the removeAllOptions() function:
In the onChange() function for selectorOne we create a variable "values" which represents selectorTwo.
values = dialog.getContentElement( 'general', 'selectorTwo' )
Before populating selectorTwo with new option values based on the option selected in selectorOne, we remove any existing options from selectorTwo:
removeAllOptions( values ); // values represents selectorTwo
Within the removeAllOptions() function the variable "combo" is assigned the value that was passed in the function call, so:
combo = values = selectorTwo.
The removeAllOptions() function calls the getSelect() function and sends it the "combo" variable as a parameter.
The "combo" variable will be assigned the value that is returned by the getSelect() function.
Within the getSelect() function the variable "obj" is assigned the value that was passed in the function call, so:
obj = combo = values = selectorTwo.
The getSelect() function can return one of three values:
A) if ( obj && obj.domId && obj.getInputElement().$ )
If obj is true AND if obj.domId is true AND if obj.getInputElement().$ returns anything other than false or null, it will return the value of obj.getInputElement().
So, if the obj variable exists and the domId property of obj is set, it will run the getInputElement() function on obj and check that the DOM property ($) is set.
getInputElement() uses the domId to return the DOM element that corresponds to the selectorTwo element.
B) If not all three parts of A were true, the getSelect() function tries:
if ( obj && obj.$ )
So, if the obj variable exists and it already is the DOM element ($), it will just send back obj.
C) If step B fails, then getSelect() returns false and selectorTwo doesn't have any option elements to remove.
Now back to the removeAllOptions() function to see what happens if step A or B of getSelect() returns something.
In both cases the "combo" variable will be the selectorTwo object with the DOM element (combo.$) set.
It runs a while loop over the array of option elements inside selectorTwo and removes them.
It gets the first option element "getChild( 0 )" and removes it, the option element that was at position Child( 1 ) moves to position Child( 0 ) and the loop continues until there are no option elements left.
The getInputElement() function is located at line ( 1085 ) of ckeditor_source\plugins\dialogui\plugin.js
The getInputElement() function calls the getElement() function.
The getElement() function is located at line ( 2560 ) of ckeditor_source\plugins\dialog\plugin.js
function removeAllOptions( combo )
{
combo = getSelect( combo );
while ( combo.getChild( 0 ) && combo.getChild( 0 ).remove() )
{ /*jsl:pass*/ }
}
function getSelect( obj )
{
if ( obj && obj.domId && obj.getInputElement().$ ) // Dialog element.
return obj.getInputElement();
else if ( obj && obj.$ )
return obj;
return false;
}
Be Well,
Joe
Yes, its totally possible to implement.. In the code, put 2 select boxes.
Then in the js code of that plugin, bind a clickhandler to the select box which puts the value u want in the second select box.