How to show attributes table in API4

2028
12
06-06-2018 02:31 AM
Highlighted
New Contributor III

4.x‌

js api 4.7

attribue table‌

How to show attributes table for a selected layer in API 4.7. I need anything similar to featuretable in API 3.

Reply
0 Kudos
12 Replies
Highlighted
Frequent Contributor

This sample is using dgrid to show the results of a query

Highlight features by geometry | ArcGIS API for JavaScript 4.7 

You can look at that sample to put together something you can use.

Highlighted
New Contributor

We have an application where we would like to display the attribute table for the feature layer small no. of rows), and then allow the user to edit directly in the attribute table, and then reflect the changes on the map e.g. popups / defined symbology. We also want the user to be able to select the item on the table and then show the selection on the map (reverse of the above mentioned example).  Is this workflow possible with JS 4.12?

Reply
0 Kudos
Highlighted
Occasional Contributor

Hi Dawn,

I have had the same problem as you with an app I have been developing. API 3.x had the FeatureTable widget that nicely and easily allowed this functionality, however this is not available in 4.x yet. FeatureTable will be available later this year in an update but until then you will have to use other functionality or libraries to do what you want to do. using dgrid is one way to do this and combining it with esri/request to make REST and POST calls to services. I personally have been using boostrap and jquery.datatables to create a table with CRUD capabilities like you described in your workflow. 

So yes this workflow is possible in 4.12 but will require some extra work until FeatureTable widget comes out later this year for 4.x esri JS API. 

Reply
0 Kudos
Highlighted
New Contributor

Thanks, David - I've gone with API 3.29 for now - FeatureTable edit works great.

But now my dilemma is.... I want the user to be able to edit the Attribute table and render the changes on the map but not actually update/apply the edits to the underlying feature service - so I either need to create some sort of disconnected clone, or I need to cancel the edits after they have been rendered on the map, but BEFORE they are applied to the underlying data! Is this even possible? Your dynamic table for 4.12 in your reply to Ahmed will give me the disconnect I need, but I am not sure I will be able to get the "edit data / refresh map / cancel edits before they are applied/sync'd back to the server" functionality.

I've tried to create a new layer from a FeatureCollection tha tcan be bound to the table, but I get a "cyclic object value" error on the new layer (Can I populate a FeatureTable with a FeatureLayer built from a query and a featureCollection? ) Would it be possible to create a separate Graphics layer from the feature service and load those contents into the FeatureTable to get the edit / refresh map / cancel edits functionality I am trying to produce?

Reply
0 Kudos
Highlighted
Occasional Contributor

Hi Ahmed,

What I have done to show attributes in a table has been to create a function in Javascript to dynamically create a table by creating div elements based on a REST response from my feature services using esri/request, which creates elements with content that is taken from the fields of the service. I then use jquery.datatables and bootstrap tables CDNs on this table to apply CSS and pagination. 

Highlighted
New Contributor III

could you show me the code

Reply
0 Kudos
Highlighted
Occasional Contributor

Here is a snippet (works but is a still a work in progress), I am using boostrap tables CDN which is the reason for the specific element classes and content.

<script type="text/javascript">

require([
"esri/request"
], function (esriRequest) {

populateAttributesTable();

//populate the attribute of a given layer
function populateAttributesTable(e) {

//alert("calling attribute table for Layer " + e.target.layerid);
let queryurl = "service url";
let queryOptions = {
responseType: "json",
query:
{
f: "json",
where:"1=1",
returnCountOnly: false,
outFields: "*",
resultRecordCount: "1000"
}
}

esriRequest(queryurl, queryOptions).then(response => {
console.log("The response is: ", response);
let tableWrapper = document.getElementById("tableWrapper");
let table = document.createElement("table");
table.id = "dataTable";
table.className = "table table-striped table-hover";
//tableWrapper.appendChild(table); //appends the table to tableWrapper
let header = document.createElement("thead");
table.appendChild(header);
let tableRowHeader = document.createElement("tr");
header.appendChild(tableRowHeader);

for (let i = 0; i < 5; i++) {
let headTable = document.createElement("th");
headTable.innerHTML = response.data.fields[i].alias;
tableRowHeader.appendChild(headTable);
}

let headTableOptions = document.createElement("th");
headTableOptions.innerHTML = "Options";
tableRowHeader.appendChild(headTableOptions);

let tableBody = document.createElement("tbody");
table.appendChild(tableBody);

for (let j = 0; j < response.data.features.length; j++)
{
let feature = response.data.features[j];
let tableRowBody = document.createElement("tr");
tableBody.appendChild(tableRowBody);
for (let i = 0; i < 5; i++)
{
let field = response.data.fields[i];
let divTable =
document.createElement("td");
divTable.innerHTML =
feature.attributes[field.name];
tableRowBody.appendChild(divTable);
}

let footerTD = document.createElement("td");
tableRowBody.appendChild(footerTD);
let editModal = document.createElement("a");
editModal.setAttribute("href", "#editModal");
editModal.className = "edit";
editModal.setAttribute("data-toggle", "modal");
footerTD.appendChild(editModal);
let editModalIcon = document.createElement("i");
editModalIcon.className = "material-icons";
editModalIcon.setAttribute("data-toggle", "tooltip");
editModalIcon.setAttribute("title", "Edit");
editModalIcon.innerHTML = "&#xE254;";
editModal.appendChild(editModalIcon);
let deleteModal = document.createElement("a");
deleteModal.setAttribute("href", "#deleteModal");
deleteModal.className = "delete";
deleteModal.setAttribute("data-toggle", "modal");
footerTD.appendChild(deleteModal);
let deleteModalIcon = document.createElement("i");
deleteModalIcon.className = "material-icons";
deleteModalIcon.setAttribute("data-toggle", "tooltip");
deleteModalIcon.setAttribute("title", "Delete");
deleteModalIcon.innerHTML = "&#xE872;";
deleteModal.appendChild(deleteModalIcon);
}

tableWrapper.appendChild(table);

require(["https://cdn.datatables.net/1.10.19/js/jquery.dataTables.js"], function () {

$(document).ready(function () {
$('#dataTable').DataTable();
$('.dataTables_length').addClass('bs-select');
// Activate tooltip
$('[data-toggle="tooltip"]').tooltip();

// Select/Deselect checkboxes
var checkbox = $('table tbody input[type="checkbox"]');
$("#selectAll").click(function () {
if (this.checked) {
checkbox.each(function () {
this.checked = true;
});
} else {
checkbox.each(function () {
this.checked = false;
});
}
});
checkbox.click(function () {
if (!this.checked) {
$("#selectAll").prop("checked", false);
}
});

});

});

});
};
});

</script>
Reply
0 Kudos
Highlighted
Occasional Contributor

Thanks for sharing David - this has hopefully set me off down a useful path. However, when I've been experimenting, I'm not getting any .features in my response, so the For loop on line 51 in your snippet is going to hit problems for me.  I get the fields no problem (for previous For loop on 38), but no features. Simplified test example below, be grateful if anyone has some advice. 

Cheers, 

Andy.

var url = "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0";
var query = {
responseType: "json",
query:
{
f: "json",
where:"1=1",
returnCountOnly: false,
outFields: "*",
resultRecordCount: "1000"
}
}

esriRequest(url, query).then(function(response) {
console.log(response);
});
Reply
0 Kudos
Highlighted
Occasional Contributor

Hi Andy,

Try this - 

//populate the attribute table with the attributes of a given layer
function populateAttributesTable(e)
{
//alert("calling attribute table for Layer " + e.target.layerid);
let queryurl = "https://giswebtst01.it.ohio-state.edu/arcgis/rest/services/OARDC/OARDC_SD/FeatureServer/2/query";
let attributetable = document.getElementById("attributetable");
attributetable.innerHTML ="";
let queryOptions = {
responseType: "json",
query:
{
f: "json",
where:"1=1",
returnCountOnly: false,
outFields: "*",
resultRecordCount: "50"
}
}
Request(queryurl,queryOptions).then (response =>
{
//alert(response.data.fields.length);
let table = document.createElement("table");
table.border = 2;
let header = document.createElement("tr");
table.appendChild(header);
//populate the fields/ columns
for (let i = 0; i < response.data.fields.length; i++)
{
let column = document.createElement("th");
column.textContent = response.data.fields.alias;
header.appendChild(column);
}
//loop through all features
for (let j = 0; j < response.data.features.length; j++)
{
let feature = response.data.features;
let row = document.createElement("tr");
table.appendChild(row);
for (let i = 0; i < response.data.fields.length; i++)
{
let field = response.data.fields;
let column = document.createElement("td");
column.textContent = feature.attributes[field.name];
row.appendChild(column);
}
}
attributetable.appendChild(table);
}, response => el.style.visibility="hidden" );
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Reply
0 Kudos