Dynamically update a table using javascript - javascript

I have a page where I send an ajax request to a server. There is a table on the page which displays some data. The server returns a json object which is a list of objects and it doesn't contain any layout for the page.
I want to update only table rows by returned json. How can I do this without using third-party libraries and only using jquery? I just want a rough idea and example.

Here is the demo fiddle. (simple version)
NEW: See the updated fiddle (advanced version).
Let's say you have this JSON data retrieved:
var jsonData = [
{ field1: 'value a1', field2: 'value a2', field3: 'value a3', field4: 'value a4' },
{ field1: 'value b1', field2: 'value b2', field3: 'value b3', field4: 'value b4' },
{ field1: 'value c1', field2: 'value c2', field3: 'value c3', field4: 'value c4' }
];
And you have this table:
<table id="data-table">
<tr><td>There are no items...</td></tr>
</table>
Now, you need a method that can parse the values in a customisable order and presence. For example, if you can pass a field array to the parser function; you can set the order of the fields and leave out a field or two if you want to:
loadTable('data-table', ['field1', 'field2', 'field3'], jsonData);
Notice that field4 is not parsed.
The loadTable function loops through the items of the returned array and create a <tr> with each field value inside a <td>. Here is the simple function:
function loadTable(tableId, fields, data) {
//$('#' + tableId).empty(); //not really necessary
var rows = '';
$.each(data, function(index, item) {
var row = '<tr>';
$.each(fields, function(index, field) {
row += '<td>' + item[field+''] + '</td>';
});
rows += row + '<tr>';
});
$('#' + tableId).html(rows);
}
UPDATE:
Added support for:
Table headers
Default text (for empty list)
Appending lists
Clearing the table
etc...
You can now simply include an empty table and the dynamicTable will take care of the rest:
<table id="data-table"></table>
Call the dynamicTable.config() method to configure the table:
var dt = dynamicTable.config('data-table', //id of the table
['field2', 'field1', 'field3'], //field names
['header 1', 'header 2', 'header 3'], //set to null for field names to be used as header names instead of custom headers
'There are no items to list...'); //default text for no items
Then call dt.load(data); to load new data (removes the previous list if there is one),
OR call dt.load(data, true); to append the new data at the end of the previous list.
Calling dt.clear(); method will clear the whole list.
Updated fiddle here.

You can iterate through your JSON objects.
$.each(JSON_Object, function(key, value) {
// Write your code here
});
Then you can simply append your table with data.
$('#yourTableName tr:last').after('<tr><td>John</td><td>$500</td></tr>');
Since you specifically mentioned that you don't need 3rd party libraries, you can do something like above. However if you need dataset with all the features, you can consider some plugin like http://datatables.net/.

If the table in question is associated to an oData service (e.g. as is standard in Fiori) with an item reference in the table XML such as items="{/ReportSet}" then a request to update the table with a filter will automatically update the table items i.e. in JS:
eTable.bindItems(sPathR,template,null,this.instanceFilter);
sPathR is the entity set e.g. /ReportSet in the above
template should be the item template in the table
this.instanceFilter is the defined filter set prior to the call

Related

Set the field values to the values from the selected record in tree Extjs

In my application, the two components Ext.tree.Panel and Ext.form.Panel
When I click on the tree entry I need to set the field values ​​to the values ​​from the selected record.
When I click on the entry, the event handler function in the controller is triggered:
...
showDataFields: function(view, record, item, index, event) {
//got a form with fields
var panel = view.up('mainpanel');
var formfield = panel.down('mainform');
//got the selected entry in the tree
sel = view.getSelectionModel().getSelection()[0];
console.log(sel)
//How to assign values from selected record to form fields?
}
...
How can i do this?
Example in fiddle
The showDataFields method in the controller file on line 37
You can use loadRecord, which will map your record data to your form by name property. First retrieve form and then set your record to it:
showDataFields: function(view, record, item, index, event) {
...
var form = panel.down('storagepaneltype');
form.loadRecord(record);
}
Also, you need to change "name" property from name to text to make form match record property. In Fiddle.view.StoragePanel:
items: [{
xtype: 'textfield',
name: 'text', //<-- here
fieldLabel: 'Наименование',
itemId: 'name_field',
value: '',
//bind: '{person.name}'
}
Here's the FIDDLE

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.

Setting id attribute to datatables 1.10.11 <tr>

I am using datatables 1.10.11.
As per the documentation, i can set the rowId using following syntax:
$('#myTable').DataTable( {
rowId: 'staffId'
} );
I am not creating datatable using Ajax.
I have two text boxes and "Add" button on left hand side and one datatable on right hand side. When i click on "Add", a new row is added to datatable. I hope that makes sense.
I need unique id attribute for each row for my use. I have tried doing so but no success at all.
According to documentation, this feature is available since DataTables 1.10.8
Did anyone solved this problem? Any help will be appreciated.
Thanks.
For add ID to tr element you con use rowId and especify the column that contain your id.
$('#myTable').DataTable(
{
columns: [
{data:"staffId"},//Remember specified the column
{data:"position"},
{data:"office"},
{data:"age"},
{data:"date"},
{data:"salary"}
],
rowId: 'staffId' //Reference to column data
});
For your button add, you should create the object and add to Table using row.add and draw for show in your table, for example:
$("#btnAdd").on("click",function(){
var rowID = $("#rowId").val();//Get value of TextBox
var new_object = {
staffId: rowID, //New rowId
position: 'Developer',
office: "Peru",
age: 25,
date: "2016/03/25",
salary: "$ 58.200"
};
myTable.row.add(
new_object
).draw();
});
Result: https://jsfiddle.net/cmedina/7kfmyw6x/65/

updated value in grid is not shown at java spring controller

I have a enhanced grid, i want to edit the grid contents and once clicked on Update link, i have to pass newly typed values to the java spring controller where i have logic to save updated values in database. But issue is after i type the value in enhanced grid i need to click somewhere in the grid or make focus on other field so that newly typed value is passed to the spring controller. If i type the new value and the cell is in edit mode and directly click on UPDATE link present in column4 of grid, the old value is passed to the spring controller. Please suggest what changes to be made so that once the mouse is out of the focus of the cell, the newly typed value should save in store and that value should be sent to spring controller when UPDATE link is clicked on column4 of grid.
Please find the fiddle : http://jsfiddle.net/740L0y43/7/
enhanced grid code:
require(['dojo/_base/lang', 'dojox/grid/EnhancedGrid', 'dojo/data/ItemFileWriteStore', 'dijit/form/Button', 'dojo/dom', 'dojo/aspect', 'dojo/domReady!'],
function (lang, EnhancedGrid, ItemFileWriteStore, Button, dom, aspect) {
/*set up data store*/
var data = {
identifier: "id",
items: [{
id : 1,
col2 : "aa",
col3 : "bb",
col4 : "cC"
}]
};
var store = new ItemFileWriteStore({
data: data
});
/*set up layout*/
var layout = [
[{
'name': 'Column 1',singleClickEdit:'true', editable:'true',
'field': 'id',
'width': '100px'
}, {
'name': 'Column 2',singleClickEdit:'true', editable:'true',
'field': 'col2',
'width': '100px'
}, {
'name': 'Column 3',singleClickEdit:'true', editable:'true',
'field': 'col3',
'width': '200px'
}, {
'name': 'Column 4',formatter: updateDetails,
'field': 'col4',
'width': '150px'
}]
];
/*create a new grid*/
var grid = new EnhancedGrid({
id: 'grid',
store: store,
structure: layout,
sortInfo: -1,
});
/*append the new grid to the div*/
grid.placeAt("gridDiv");
/*Call startup() to render the grid*/
grid.startup();
aspect.after(grid, 'renderRow', grid.sort);
var id = 2;
var button = new Button({
onClick: function () {
console.log(arguments);
store.newItem({
id: id,
col2: "col2-" + id,
col3: "col3-" + id,
col4: "col4-" + id
});
id++;
}
}, "addRow");
});
var updateDetails = function(value, rowIndex) {
var col2 = this.grid.getItem(rowIndex).col2;
alert("col2 updated value : " + col2);
return "<a href=\"<%=request.getContextPath()%>/updateInfo.htm?col2="+col2 +"\">" + "UPDATE";
};
spring controller code:
#RequestMapping(value = "/updateInfo", method = RequestMethod.GET)
public ModelAndView updateInfo(HttpServletRequest request,
HttpServletResponse response, #ModelAttribute MyDTO myDto,
#RequestParam("col2") String col2, #RequestParam("col2") String col2){
System.out.println("col2 value: " + col2);
System.out.println("col3 value: " + col3);
//when i type some value in COlumn2/Column3 of enhanced grid and column is still in edit mode then on click of UPDATE , new value is not passed to spring controller, its passing the old value.
...
...
//logic to save in DB
}
This line:
return "<a href=\"<%=request.getContextPath()%>/updateInfo.htm?col2="+col2 +"\">" + "UPDATE";
is returning an anchor with the href as "/contextPath/updateInfo.html?col2=aa". That renders it and that's it; that URL is never changing. Then, when you click on UPDATE, it sends what was in there when the page was rendered, not what the current value in your table is.
If you want to have the current value be sent, you should have your href be "#" and have an onclick="updateValue(1)" like this:
UPDATE
where 1 is the row number.
Then, in your update value function, you'd send an ajax request to update the value. Since you're using dojo, check this out: http://dojotoolkit.org/documentation/tutorials/1.8/ajax/
Here's what your function might look like (some pseudo code, some comments to describe behavior):
function updateValue(rowNum){
//var row = data.items.getRow(rowNum); or something like this
//Call ajax here and send the new row values
}
After messing with dojo for about an hour, and struggling with dojo's scoping and how to call a function that has access to the data grid and/or it's data store (sorry..I had 0 experience with dojo before this question)...here's your easy way out, OP:
http://jsfiddle.net/hm8gpz6o/
The important parts:
EnhancedGrid was NOT re-rendering the formatter generated cell when your data store was updated. This seems like a problem with dojo's EnhancedGrid.
I added the following (onApplyCellEdit will fire when a cell is updated):
/*create a new grid*/
var grid = new EnhancedGrid({
id: 'grid',
store: store,
structure: layout,
sortInfo: -1,
onApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
refreshGrid();
}
});
And finally, refreshGrid() will force a re-render of the whole grid. I hate that I have to do this:
function refreshGrid(){
grid.startup();
}
Please see the fiddle for the full working example.

delete row(s) from ng-grid table from button

I have a table with ng-grid, and the problem is that i'm not sure how to collect the selected row(s) id or variable to pass into my delete function.
here is a quick mockup of what i'm trying to do
http://plnkr.co/edit/zy653RrqHmBiRJ7xDHlV?p=preview
the following code is from my html, a clickable delete button that takes in 2 parameters, the array of checkbox ids and the index at the corresponding table. This delete method was obtained from this tutorial : http://alexpotrykus.com/blog/2013/12/07/angularjs-with-rails-4-part-1/
<div class="btn-group">
<button class="my-btn btn-default button-row-provider-medical-services" ng-click="deleteProviderMedicalService([], $index)">Delete</button>
</button>
</div>
<div class="gridStyle ngGridTable" ng-grid="gridOptions">
</div>
The following code grabs the json data from a url, queries it and returns it. It also contains the delete function that gets called from the controller in the html page.
app.factory('ProviderMedicalService', ['$resource', function($resource) {
function ProviderMedicalService() {
this.service = $resource('/api/provider_medical_services/:providerMedicalServiceId', {providerMedicalServiceId: '#id'});
};
ProviderMedicalService.prototype.all = function() {
return this.service.query();
};
ProviderMedicalService.prototype.delete = function(providerId) {
this.service.remove({providerMedicalServiceId: providerId});
};
return new ProviderMedicalService;
}]);
The following is my controller(not everything, just the most important bits). $scope.provider_medical_services gets the json data and puts it into the ng-grid gridOptions.
After reading the ng-grid docs, i must somehow pass the checkbox ids from the selectedItems array and pass it into html doc to the delete function. Or, i'm just doing this completely wrong, as i hacked this together. Solutions and suggestions are greatly appreciated
(function() {
app.controller('ModalDemoCtrl', ['$scope', 'ProviderMedicalService', '$resource', '$modal', function($scope, ProviderMedicalService, $resource, $modal) {
var checkBoxCellTemplate = '<div class="ngSelectionCell"><input tabindex="-1" class="ngSelectionCheckbox" type="checkbox" ng-checked="row.selected" /></div>';
$scope.provider_medical_services = ProviderMedicalService.all();
$scope.deleteProviderMedicalService = function(ids,idx) {
$scope.provider_medical_services.splice(idx, 1);
return ProviderMedicalService.delete(ids);
};
$scope.gridOptions = {
columnDefs: [
{
cellTemplate: checkBoxCellTemplate,
showSelectionCheckbox: true
},{
field: 'name',
displayName: 'CPT Code/Description'
},{
field: 'cash_price',
displayName: 'Cash Price'
},{
field: 'average_price',
displayName: 'Average Price'
},
],
data: 'provider_medical_services',
selectedItems: []
};
i think the easiest option is pass an (array index) as data-id to your dom, which u can pick it from there.
{{$index}} is a variable you can use in ng-repeat
======= ignore what i said above, since i normaly writes my own custom stuff ======
I just had a look at ng-grid, i took their example. i've added a delete all selected function, as well as someone elses delete current row function ( these is pure angular way ) to see the code, hover over the top right corner < edit in jsbin >
http://jsbin.com/huyodove/1/
Honestsly i don't like it this way, you would be better off use something like lodash to manage your arrays and do your own custom grid. Using foreach to find the row index isn't good performance.
In their doc, it says you can change the row template, and which you should, so you can add the {{index}} to that row, and filter your data through that index rather which is a little bit better. anyway beware of deleting cells after you have filter your table.
I don't quite get much your question, but you can access to selectedItems of ng-grid as following: $scope.gridOptions.$gridScope.selectedItems (see ng-grid API for more information, but technically this array holds the list of selected items in multiple mode - or only one item in single mode)
For your case, the deleteAll() function could be someething like this:
$scope.deleteAll = function() {
$scope.myData = [];
}
The delete() function which delete selected items can be:
$scope.delete = function() {
$.each($scope.gridOptions.$gridScope.selectedItems, function(index, selectedItem) {
//remove the selected item from 'myData' - it is 2-ways binding to any modification to myData will be reflected in ng-grid table
//you could check by either name or unique id of item
});
}

Categories

Resources