Slickgrid - Change Editor of Single Cell, and not Entire Column - javascript

Here's the scenario:
There are a number of rows of selectable data
One column (#1) has dropdown editor with two options
The next column (#2) can have either a text editor, or dropdown editor - depending on the option selected in the first dropdown, see example:
_________Column #1_________|_________Column #2_________
1     select opt 1      |      *dropdown editor*    
2     select opt 1      |      *dropdown editor*    
3     select opt 1      |      *dropdown editor*    
4     select opt 2      |      *text editor*         <--- is this possible?
5     select opt 1      |      *dropdown editor*    
6     select opt 1      |      *dropdown editor*    
Is it even possible to change the editor of a single cell based on the input/change of another cell? It appears as though you can't change editors on a cell level, but only on a column level.
Any help is greatly appreciated, many hours spent on this already; and haven't found a solution or even similar question. Thanks
Update
This is getting close perhaps:
var currentRowIndex = object.grid.getActiveCell().row,
nextCellIndex = object.grid.getActiveCell().cell + 1;
object.grid.setActiveCell(currentRowIndex, nextCellIndex);
object.grid.editActiveCell(this.editors.textEditor);
But this doesn't ensure that the editor remains; for example^ a text editor. When changing the value in the first column (#1), and enabling the text editor in column #2 as above - after this edit takes place - the original editor is still in place in column #2.
I want the editor to remain the same - but can't find how to do this on a cell level rather than a column level. Thanks

Browsing the source (getEditor line 1381) pertaining to the retrieval of editors reveals a few different options are available.
column metadata
column definition
editorFactory grid option
Given that you require a different column value from within the row, I would approach the problem using the column metadata as it receives the rowIndex as an argument.
var viewModel = {options: ['LongText', 'Text', 'Checkbox']}
function apply() {
var grid, data = [];
var options = {
editable: true,
enableCellNavigation: true,
asyncEditorLoading: false,
autoEdit: true,
forcefitColumns: false
};
var columns = [{
id: "data",
name: "Editor Type",
field: "type",
width: 120,
cssClass: "cell-title" ,
formatter: function(row){
var key = 'input'+row;
if(!viewModel[key]){
viewModel[key] = ko.observable();
viewModel[key].subscribe(function(nv){
data[row].type = nv
})
}
setTimeout(function(){ ko.applyBindings(viewModel, document.getElementById(key)) }, 250);
return '<select id="'+key+'", data-bind="options: options, value: '+key+'"></select>'
}
},
{
id: "other",
name: "Other",
field: "other",
width: 120,
cssClass: "cell-title",
}];
for (var i = 0; i < 5; i++) {
var d = (data[i] = {});
d["type"] = "";
d["other"] = "Default " + i;
}
grid = new Slick.Grid("#myGrid", data, columns, options);
//ko.applyBindings(viewModel)
data.getItemMetadata=function(row){
var rowData = data[row]
//console.log(rowData)
var metaData = {columns:{other: {}}}
metaData.columns.other.editor = Slick.Editors[rowData.type]
return metaData
}
}
apply()
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<link rel="stylesheet" type="text/css" href="http://JLynch7.github.io/SlickGrid/slick.grid.css">
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
<script src="http://JLynch7.github.io/SlickGrid/slick.dataview.js"></script>
<script src='http://mleibman.github.io/SlickGrid/lib/jquery.event.drag-2.2.js'></script>
<script src='http://JLynch7.github.io/SlickGrid/slick.core.js'></script>
<script src='http://JLynch7.github.io/SlickGrid/slick.grid.js'></script>
<script src='http://JLynch7.github.io/SlickGrid/slick.formatters.js'></script>
<script src='http://JLynch7.github.io/SlickGrid/slick.editors.js'></script>
<div id='container'>
<div id="myGrid" style="width:600px;height:300px;"></div>
</div>

Related

Change select field options in client script in NetSuite

I have a client script runs on Suitelet.
On Suitelet we have a sublist which has many select columns.
Let's say we have Select 1 and Select 2.
Select 2 options should be different if you change the option in Select 1.
Could this be done in Client Script? or in that Suitelet?
Any help would be appreciated.
`
var select1= sublist.addField({
id: 'custpage_select1',
label: 'Select1',
type: ui.FieldType.SELECT
});
var select2= sublist.addField({
id: 'custpage_select2',
label: 'Select2',
type: ui.FieldType.SELECT
});
`
In client script when the field is changed, I want to change options of Select 2 depend on Select 1.
function fieldChanged(scriptContext){
if(scriptContext.fieldId=="custpage_select1"){
let page = currentRecord.get();
var select2 = page.getField({fieldID:"custpage_select2"});
select2.removeSelectOption({value:"value1"});
}
}
But this shows me an error that
Cannot read properties of null
Thank you
Yes. You can use the N/currentRecord module in your client script with getField() and removeSelectOption().
let page = currentRecord.get();
const select2 = page.getField({
fieldId: 'custpage_select2'
});
select2.removeSelectOption({
value: 'option1'
});

How do I add a blank row to table using FooTable v3

FooTable v2 allowed users to inject DOM elements - rows into a table - and sorting still kinda works. FooTable v3 is a complete re-write and the data in the table is completely managed by FooTable. The original DOM is restructured by FooTable.init. Adding to the DOM will mean FooTable sorting and filtering will be unaware of the added record. As far as I can tell, the proper way to add a new row to the FooTable v3 is to call the editing component's function 'addRow'.
The original author of FooTable has assumed many things - such as the developer will want to use a popup asking for values. In my case, when adding a row I do not want an editor window popping up asking for values. I merely want to add a blank row to the table programatically/dynamically without using any footable UI components.
How do I call this function? What is the proper syntax.
I init my table via ...
$(document).ready(function () {
$('.my-footable').footable({
"editing": {
"enabled":"true"
}
});
});
... and I have a click event on a button...
$(document).on("click", "#myButton", function (event) {
var editing = FooTable.get(".my-footable").use(FooTable.Editing);
});
... but I am stumped on how to invoke addRow - and what parameters I pass...
Any ideas?
$(document).ready(function() {
var columns_name = ['id', 'first name', 'last name', 'job title'],
columns = [],
rows = [{
'id': 1,
'first_name': 'Dennise',
'last_name': 'Fuhrman',
'job_title': 'High School History Teacher'
}];
/**
Creating a new object with the help of columns_name array with
having key title and name and then pushing it to the columns array. We'll
pass that array in the footable init object.
*/
for (var i = 0; i < columns_name.length; i++) {
var column = columns_name[i];
/**
In name key replacing spaces with underscore so that it will match with
the keys in row array of object
*/
columns.push({
title: column,
name: column.replace(/ /g, "_")
});
}
var ft_init_options = {
columns: columns,
rows: rows,
editing: {
enabled: true,
alwaysShow: true,
allowAdd: true,
allowEdit: false,
addRow: function() {
/**
Creating new row with empty columns having input field
*/
var values = {
'id': '<input type="text">',
'first_name': '<input type="text">',
'last_name': '<input type="text">',
'job_title': '<input type="text">'
}
ft.rows.add(values);
},
deleteRow: function(row) {
if (confirm('Are you sure you want to delete the row?')) {
row.delete();
}
}
}
};
var ft = FooTable.init('#editing-example', ft_init_options);
});
/**
Remove the following comments if you want to remove the border from the inputs
and want to display when they are in focus
*/
/**
textarea:focus, input:focus{
border-width: 2px;
border-style: inset;
border-color: initial;
border-image: initial;
}
textarea, input {
border : none;
}
**/
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://fooplugins.github.io/FooTable/compiled/footable.bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-footable/3.1.6/footable.js"></script>
<div class="container-fluid">
<hr>
<h1 class="text-center"> FooTable Editing Example with inputs in row</h1>
<hr>
<table id="editing-example" class="table"></table>
</div>
If code snippet is not working then have a look on jsfiddle

How to remove an empty option after a filter modifies the drop down list in Angular?

I'm using Angularjs 1.4.2 and I have to create a drop down list that is a combination of numbers and text. It is an array of objects with two properties. So I use numbers as a type of label and convert the 0 value and the -1 values to text as the top and bottom of the list.
The reason I don't just hard code the text is inside the filter we call a service to change the language of the text for the page, which makes it dynamic for switching languages and hence the reason I opted for a number labeling system for the option entries.
However, I keep getting a blank option in the list and the default "Select Item" text for 0 cannot get pre-selected when the drop down appears.
What I found was that
the empty option is generated when a value referenced by ng-model
doesn't exist in a set of options passed to ng-options
In this case, the original list that was put in scope
has been modified by the filter, so I assume that is why the empty option appears in the drop down list.
My code works fine without the filter, but when I try to apply the filter, I get this error:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
The drop down list does have the correct values from the filter, but the empty option is still there and it is selected instead of the text "Select Item", which is what I want.
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.4.2" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-controller="Test">
<p>selected item is : {{selectedItem}}</p>
<p> The distance of selected item is : {{selectedItem.distance}} </p>
<select ng-model="selectedItem" ng-options="item.distanceSize for item in items | myFilter" ng-init="selectedItem = items[0]">
</select>
</div>
</body>
</html>
script.js
var app = angular.module('app',[]);
app.controller('Test',function($scope){
$scope.items = [{"distance": "0", "distanceSize": 0},{"distance": "25", "distanceSize": 25},{"distance": "50", "distanceSize": 50},{"distance": "-1", "distanceSize": -1}];
});
app.filter('myFilter', function () {
return function (items) {
var valuesArray = [];
if(items) {
for(var i = 0; i < items.length; i++) {
var myObject = {};
if(items[i].distanceSize === 0) {
myObject.distanceLabel = "0";
myObject.distanceSize = "Select Item";
valuesArray.push(myObject);
}else if(items[i].distanceSize == 25) {
myObject.distanceLabel = "25";
myObject.distanceSize = 25;
valuesArray.push(myObject);
}
else if(items[i].distanceSize == 50) {
myObject.distanceLabel = "50";
myObject.distanceSize = 50;
valuesArray.push(myObject);
}
else if(items[i].distanceSize == -1) {
myObject.distanceLabel = "-1";
myObject.distanceSize = "Select Everything";
valuesArray.push(myObject);
}
}
}
return valuesArray;
};
});
Since my drop down list is modified by the filter, how to I remove or mask the empty option and why is the filter throwing errors?
10 $digest() iterations reached. Aborting!
This is a well known issue. I'd refer to this Stack Overflow question: How to Troubleshoot Angular “10 $digest() iterations reached” Error, specifically its answer about returning new objects. Every time angular calls myFilter it gets a new valuesArray that does not === the old valuesArray. Angular sees this as a change and calls the filter again and again, until it aborts with the error.
Rather than applying your filter to the entire array, apply the filter to the label. This changes your ng-options from:
ng-options="item.distanceSize for item in items | myFilter"
to
ng-options="item as (item.distanceSize | myFilter) for item in items"
Then change your filter to handle a single item:
app.filter('myFilter', function () {
return function (distanceSize) {
if (distanceSize === 0)
return "Select Item";
if (distanceSize === -1)
return "Select Everything";
return distanceSize;
}
});
You can see an example in this plunker.
The empty option is present because $scope.selectedItem is a null value. You can either set it to a default value (like I did in the plunker) or you can hard code a single element, with the value set to an empty string. This element will then represent the null or "not selected" option. This could replace your "Select Item" option. You can find more information about this in the ngOptions documentation.

How to get selected index value from list box

This is a code for my customised DropDownList:
<script type="text/javascript">
$(document).ready(function () {
var source = [ "Alappuzha","Eranakulam","Idukki" ];
// Create a DropDownList
$("#Widget").jqxDropDownList({autoOpen: true, source: source, selectedIndex: 1, width: '241', height: '30'});
});
</script>
<div id='Widget' >
</div>
How can I get the selected index value from the above list box using javascript?
You can use the API of jqxDropDownList widget:
var selectedIndex = $('#Widget').jqxDropDownList('selectedIndex');

Saving dynamically generated jqgrid columns

I have a jqgrid with generated columns like this (in a ASP.NET MVC 3 project). They use inline editing :
#foreach (var template in Model.TemplateList.Where(m => m.Type == 2))
{
<text>
{ name: 'A'+'#template.ID', index: 'A'+'#template.ID', width: 40, align: 'left',
editable: true,
editoptions: { dataEvents: [{ type: 'keyup', fn: function (e) {
var $tr = $(e.target).closest("tr.jqgrow"), rowId = $tr.attr("id");
var nextRow = parseInt(rowId, 10) + 1;
var total = parseInt(e.target.value, 10);
if (isNaN(total)) {
total = 0;
}
ChangeValue('A'+'#template.ID', total, $tr);
}}]}},
</text>
}
The columns are generated and work well, until I try to save them. I'm trying to give the value to the controller, but it doesn't seem to work. I already tried to give the same name to all column to get them in an array :
... name: 'templateColumns', index: 'A'+'#template.ID', width: 40, align: 'left', ...
and in the controller :
public ActionResult SaveRow(string[] templateColumns)
but it didn't work (I only got the value of the last column)
I think you can not have same names for all the columns, check the link i gave u in comments. Now if you give one column name as ''A'+'#template.ID'' and lets suppose it is getting rendered like A1, A2 then in your controller you should accept something like this only.
public ActionResult SaveRow(string A1, string A2)
Your column name and parameters in controller should be same.

Categories

Resources