Adapt-strap/angular dynamic table column - javascript

I was having a look at the adpt-strap table lite and was playing around with it. here is the JSfiddle that I was playing about with: http://jsfiddle.net/cx5gm0sa/
What I was trying to do and I was wondering if it is possible is to try and dynamically hide/show a column. The code I have added consists of $scope.showColumn = true; (you can see the value of this on the html page, I am printing it out at the top).
When you click the buy button on any row the variable gets set to the opposite of what it was before so it alternates between true and false.
$scope.buyCar = function (car) {
$scope.showColumn = !$scope.showColumn
};
This variable is also what is used for the visible property of the model column, however when the variable changes the column doesn't hide/show as I would have expected, it only ever seems to hide/show depending on what value the variable was initialized with. Is there anyway to make this work dynamically as I originally expected it would have and does anyone know why it wouldnt be working that way already?
Thanks in advance for any help I may get.

Got it. OK, I think the reason the table does not update is because your controller does not re-run the code that defines the table when you click the Buy button. I have changed this so that instead of assigning the array of the configs to the $scope.carsTableColumnDefinition directly, I defined a function named getDefinition that returns the array instead. Then in the $scope.buyCar = function (car){}, I then call the function.
So here are the changes I made:
$scope.carsTableColumnDefinition = getDefinition();
...
//Then inside the buyCar function I have:
$scope.buyCar = function (car) {
$scope.showColumn = !$scope.showColumn;
//now refresh by calling the get-definition function:
$scope.carsTableColumnDefinition = getDefinition();
};
..
//Finally, this is my getDefinition function:
function getDefinition(){
return [
{
columnHeaderDisplayName: 'Model',
displayProperty: 'name',
sortKey: 'name',
columnSearchProperty: 'name',
visible: $scope.showColumn
},
{
columnHeaderTemplate: '<span><i class="glyphicon glyphicon-calendar"></i> Model Year</span>',
template: '<strong>{{ item.modelYear }}</strong>',
sortKey: 'modelYear',
width: '12em',
columnSearchProperty: 'modelYear'
},
{
columnHeaderTemplate: '<span><i class="glyphicon glyphicon-usd"></i> Price</span>',
displayProperty: 'price',
cellFilter: 'currency',
sortKey: 'price',
width: '9em',
columnSearchProperty: 'price'
},
{
columnHeaderDisplayName: 'Buy',
templateUrl: 'src/tablelite/docs/buyCell.html',
width: '4em'
}
];
}
I updated the jsfiddle - check it out.

Related

Input field in Table "keeps" edited number in same row while scrolling (JSView)

I've got a sap.ui.table.Table with Input fields and the table gets the data via JSON which works well. However, if I edit the value in the first row for example, and try to scroll down, the value "stays" in the first row until a different value hits this field. So it basically updates every cell except the edited one while scrolling. After that, I scroll up again to see the value I changed, but this value now has the old value from the load at the beginning again.
I think something with my binding isn't correct at all, because I haven't seen anything like this yet. I know that tables only update the row contexts but I can't figure out how to do this.
Here is a example: https://jsbin.com/yuvujozide/6/edit?html,console,output
Edit the right "Gates" and scroll, to see how it disappears and edit the left value and scroll to see how the value scrolls with the table.
I tried to remove/set the VisibleRowCount and logged to see if the data gets loaded multiple times but that's not the case.
var oModel = new sap.ui.model.json.JSONModel();
var oTable = new sap.ui.table.Table({
visibleRowCount: 12,
selectionMode: sap.ui.table.SelectionMode.Single,
visibleRowCountMode: sap.ui.table.VisibleRowCountMode.Fixed,
editable: true
});
oModel.setData({ rows: tableRows.value, columns: columnArray });
oTable.setModel(oModel);
var counter = 0;
oTable.bindColumns("/columns", function (sId, oContext) {
var columnName = columnArray[counter];
var defaultTemplate = new sap.m.Input({
value: "{" + columnName + "}"
}).bindProperty("value", columnName, function (cellValue) {
return returnRange(this, oTable, cellValue, columnName, counter, dic);
});
counter++;
return new sap.ui.table.Column({
label: columnName,
template: defaultTemplate,
flexible: true,
autoResizable: true,
width: 'auto',
multiLabels: [
new sap.ui.commons.Label({ text: columnName }),
new sap.ui.commons.Label({ text: dic[Number(counter - 1)].value[0] + " - " + dic[Number(counter - 1)].value[1] })
]
});
});
oTable.bindRows("/rows");
As you can see I separated the rowData and columnNames in two arrays:
tableRows and columnArray
The returnRange function checks some values and just returns the cellValue
I would expect that the Input fields keeps the changed values (which is probably normal), so I can change several Input fields and then I can Update the table via Ajax-Call.
The problem is that sap.ui.table.Table has a custom scrolling behaviour that is different from the default browser scrolling. Instead of creating a row for each record, it will create a fixed number of rows and re-bind these rows after each scroll.
If the table is editable and bound to a JSONModel, it will usually create a two-way-binding and update the model values upon user input, hence scrolling works fine. But since you have provided a custom formatter function for the binding (returnRange), a two-way-binding is not possible anymore. This means that any user input is lost after scrolling.
If you remove the formatter function like this
var defaultTemplate = new sap.m.Input({
value: "{" + columnName + "}"
});
it will work fine.
In case you want to validate the user input, you should listen to the input's change event and use InputBase#setValue to set it to a different value. This will also reflect your changes in the JSONModel.

Non editable kendo grid ID

I'm new using kendo grid UI, i'm trying to make a non editable column (when updating) using a simple code :
schema: {
id: 'ID',
fields: {
id: { editable: false }
}
}
This default schema, makes by default non editable id column, and i can't even create a new row with id .
I want to make it non editable (when updating) but i want the possibility to create a row and assign an id from user (when creating).
Any ideas ?
Edit :
PS : the proprety is not related to only id, it can be on every column (can't update but can create)
The editable required a function instead of a value.
columns: [
{ field: 'value', editable: function () { return false; } }
],
Checkout here:
https://dojo.telerik.com/oROJayAd
I always doubt about that model editable option. It never really worked for me. It should have something very deep in the setup to make it work which I never realized what it. So this is a way to acomplish what you need that I know it indeed works: To cancel the edit event. Check it out:
edit: function(e) {
// Cancels a new row
if (arguments, e.model.isNew()) {
this.cancelRow(e.container.parent());
}
else { // Cancels a cell editing
this.closeCell(e.container);
}
}
Demo
Now, if you like to add a condition in that event based on what you have set in your model, you can access it within event as well:
edit: function(e) {
let currentColumn = this.options.columns[e.container.index()].field,
model = this.dataSource.options.schema.model.fields[currentColumn];
if (model.editable === false) {
// Cancels a new row
if (arguments, e.model.isNew()) {
this.cancelRow(e.container.parent());
}
else { // Cancels a cell editing
this.closeCell(e.container);
}
}
}
Demo
You can add an option yourself in the model to set if the column can be updated or only created, and handle that information inside the event, canceling the editing whenever you like.
This is how I just did it, though there are other ways.
In columns option if you remove the field option from a column it doesn't know from where to bind it.
Then use the template option to show(bind) the id. Thus making it readonly
columns: [
{
title: 'Id', width: "40px",
template: "#= id #",
},
...]

Highlight on cell change (perhaps disable lazy loading)

So in a normal table, I have this directive:
app.directive('highlightOnChange', function () {
return {
link: function (scope, element, attrs) {
attrs.$observe('highlightOnChange', function (val) {
element.addClass('flight-item-highlighted');
setTimeout(function () {
element.removeClass('flight-item-highlighted');
}, 300);
});
}
};
});
this works fine when used like this in an table:
<td highlight-on-change="{{value}}" ng-repeat="(key,value) in items"></td>
The idea is to highlight the specific cell once it is updated. This is needed because it is a realtime application, meaning changes will come from the server and needs to be highlighted when changed to let the user know.
But now I am using Angular UI-Grid which lazy loads the data (which is nice for performance) but not so nice for this feature.
I was able to implement it by defining a cell template:
<div class="ui-grid-cell-contents" highlight-on-change="{{grid.getCellValue(row, col)}}">{{grid.getCellValue(row, col)}}</div>
put it in the options:
$scope.tableColumns = [
{ field: 'name', displayName: 'Firstname', width:100, visible: true, cellClass: self.cellClass, cellTemplate: '/Templates/gridcelltemplate.html' },
{ field: 'gender' }, { field: 'company' }];
$scope.gridOptions = {
data: self.data,
columnDefs: self.tableColumns,
enableColumnResizing: true,
enableColumnMenus: false,
rowTemplate: '/Templates/rowtemplate.html',
headerTemplate : '/Templates/headertemplate.html',
};
But the result is that elements are always highlighted on scroll, obviously because they are created at that point (It does work nice for a single update though).
So one solution that I think of would be to change the css class from the controller for a specific column when the data has changed. But because the index will change on scroll for a particular row it would not make any sense. (Because row indexes are always from 0 to x, where x is the last shown row).
Another solution I can do is to keep the same directive, give a function that would call my controller. Controller would somehow need to check if the value is new or not and if so return true. Which would then result in an highlight.
inside directive:
....
scope: {
changed: '&',
},
link: function (scope, element, attrs) {
attrs.$observe('highlightOnChange', function (val) {
//now observed value of column, it has changed, call controller to check if it is a new value
var result = scope.changed({ val: val });
....
html template:
<div class="ui-grid-cell-contents" highlight-on-change="{{grid.getCellValue(row, col)}}" changed="grid.appScope.columnChanged(val)">{{grid.getCellValue(row, col)}}</div>
To be honest, I rather have lazy loading disabled, that would solve a lot of problems actually.
Edit:
Well, I found by setting gridOptions.virtualizationThreshold: self.data.length the lazy loading is disabled. But of course this comes with some major performance issues (having about 20 columns, 1000 rows). So perhaps an more elegant way would be nice :)

Dynamic default value for Kendo Grid

I want an auto increment column in my Kendo Grid. This field isn't server side auto increment, because I want the user to see the value and be able to change it.
My current solution is to add a click attribute to Create button and loop over rows to find the highest value and increment it.
But how can I insert this value inside the newly created row? Click event happens before the new row is created.
So there is two possible solution:
Have a variable as default value and update it in my JS code.
Access the newly created row somehow, and update the value.
This is my JS code:
function createClick(id) {
var grid = $("#" + id).data('kendoGrid');
var highestRadif = 0;
grid.tbody.find('>tr').each(function () {
var dataItem = grid.dataItem(this);
var radif = dataItem.SRadifReqR;
highestRadif = highestRadif < radif ? radif : highestRadif;
})
alert(++highestRadif);
}
You can use Grid's edit event to add your new generatedId value to new Grid's model.
This is some explanation from their documentation:
Edit
fired when the user edits or creates a data item.
e.container jQuery, jQuery object of the edit container element, which wraps the editing UI.
e.model kendo.data.Model, The data item which is going to be edited. Use its isNew method to check if the data item is new
(created) or not (edited).
e.sender kendo.ui.Grid, The widget instance which fired the event.
I suppose your click have something like this
//generate id code
vm.newId = ++highestRadif; // we need to store generated Id
grid.addRow();
then on edit event
edit: function(e) {
var model = e.model; // access edited/newly added model
// model is observable object, use set method to trigger change event
model.set("id", vm.newId);
}
Note: Your schema model's field must set property editable: true, due to enable us to change model field value using set method. Also if your field schema have validation required, you need to remove it.
model: {
id: "ProductID",
fields: {
ProductID: { editable: true, nullable: true },
}
}
Sample
I was able to put a function in the datasource schema for this.
schema: {
model: {
id: "id",
fields: {
currencyType: { defaultValue: getDefaultCurrency },
invoiceDate: { type: "date" }
}
}
}
function getDefaultCurrency() {
return _.find(vm.currencyTypes, { id: vm.currencyId });
};

ng-grid change sorting order onchange of drop down

I am using ng-grid , i have implemented search functionality on it but i want to change orderby option by changing drop down value.
I wish to provide drop down on change of its value data soting should happen.
by default Sort-functionality is there which works on click of table heading but i need to change sorting order on change of dropdown.
This code i got from somewhere but i dont know how to use it ?
$scope.gridOptions = {
data: 'gridData',
columnDefs: [
{field: 'name', displayName: 'Name'},
{field:'ageWord', displayName: 'Age'}
],
sortInfo: {
fields: ['age'],
directions: ['asc']
}
};
You need to define values for the sortInfo and useExternalSorting of your grid options, like this:
$scope.gridOptions.useExternalSorting = true;
$scope.gridOptions.sortInfo = {
fields: [$scope.selectedDropDownOption], // <-- or whatever variable used to store selected option from dropdown
directions: ['asc']
};
e.g.: if you want to sort by name, you could set
sortInfo: { fields: ['name'], directions: ['asc']}
this would order your grid by name and ascending
you also want to set useExternalSorting = true in your gridOptions.
i suggest you have a look at the docu and examples pages
I used following code ,,,
HTML :
<input type="text" ng-model="sortColumn"></input>
<button type="button" class="btn" ng-click="updateSortInfo()">Sort</button>
aap.js ::
$scope.updateSortInfo = function() {
$scope.gridOptions.sortBy($scope.sortColumn);
}
Reached here while searching for solution of similar thing. After trying all options I have applied this.
//Disable Grid Ui Sorting through header
$scope.gridOptions.enableSorting = false;
//Apply angular 'orderBy' filter to data for grid ui
$scope.resultSetTable = $filter('orderBy')($scope.gridData, 'YOUR_SORT_COLUMN');
// Apply data to grid ui
$scope.gridOptions.data = $scope.resultSetTable;

Categories