Prevent Popup template to shows multiple feature in ArcGIS 4.16 Angular 10 - arcgis

I have integrated a popup on the map for a specific layer. Some time the poup shows pagination (featureNavigation) multiple data. Sometimes it fails to show the data, or mismatch in the data that actually the service returns.
var popupTrailheads = {
title: "ID: {ID}",
content: this.getcustomcontent.bind(this),
};
// Add layer special layer
this.layer_fifteen = new FeatureLayer({
url: `${this.esriURL}/15`,
visible: true,
outFields: ['*'],
popupTemplate: popupTrailheads,
});
getcustomcontent(feature) {
// The popup content will become here from angular service
return `<div>content</div>`;
}
I have a few options to fix the issue.
1)Popup for this layer enables only at a specific Zoom level. Else the popup won't appear.
2)The click on the map should trigger only for a point. (I believe when click on the layer it triggers multiple points that is the reason it shows multiple feature details.)
Can you please suggest an idea, how to enable a popup in specific zoom level, or select only one feature in one click on the map.
Thanks in advance.

So, there are a number of possible ways to enable the popup under certain conditions, like the zoom level of the view.
In the example that I made for you popup only opens if zoom is greatest than 10.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>PopupTemplate - Auto Open False</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.15/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
var populationChange;
require(["esri/Map", "esri/views/MapView", "esri/layers/Layer"], function (
Map,
MapView,
Layer
) {
var map = new Map({
basemap: "dark-gray"
});
var view = new MapView({
container: "viewDiv",
map: map,
zoom: 7,
center: [-87, 34]
});
var highlightSelect = null;
Layer.fromPortalItem({
portalItem: {
id: "e8f85b4982a24210b9c8aa20ba4e1bf7"
}
}).then(function (layer) {
map.add(layer);
var popupTemplate = {
title: "Population in {NAME}",
outFields: ["*"],
content: [{
type: 'fields',
fieldInfos: [
{
fieldName: "POP2010",
format: {
digitSeparator: true,
places: 0
},
visible: false
},
{
fieldName: "POP10_SQMI",
format: {
digitSeparator: true,
places: 2
}
},
{
fieldName: "POP2013",
format: {
digitSeparator: true,
places: 0
}
},
{
fieldName: "POP13_SQMI",
format: {
digitSeparator: true,
places: 2
}
}
]
}],
};
layer.popupTemplate = popupTemplate;
function populationChange(feature) {
var div = document.createElement("div");
var upArrow =
'<svg width="16" height="16" ><polygon points="14.14 7.07 7.07 0 0 7.07 4.07 7.07 4.07 16 10.07 16 10.07 7.07 14.14 7.07" style="fill:green"/></svg>';
var downArrow =
'<svg width="16" height="16"><polygon points="0 8.93 7.07 16 14.14 8.93 10.07 8.93 10.07 0 4.07 0 4.07 8.93 0 8.93" style="fill:red"/></svg>';
var diff =
feature.graphic.attributes.POP2013 -
feature.graphic.attributes.POP2010;
var pctChange = (diff * 100) / feature.graphic.attributes.POP2010;
var arrow = diff > 0 ? upArrow : downArrow;
div.innerHTML =
"As of 2010, the total population in this area was <b>" +
feature.graphic.attributes.POP2010 +
"</b> and the density was <b>" +
feature.graphic.attributes.POP10_SQMI +
"</b> sq mi. As of 2013, the total population was <b>" +
feature.graphic.attributes.POP2013 +
"</b> and the density was <b>" +
feature.graphic.attributes.POP13_SQMI +
"</b> sq mi. <br/> <br/>" +
"Percent change is " +
arrow +
"<span style='color: " +
(pctChange < 0 ? "red" : "green") +
";'>" +
pctChange.toFixed(3) +
"%</span>";
return div;
}
view.popup.autoOpenEnabled = false; // <- disable view popup auto open
view.on("click", function (event) { // <- listen to view click event
if (event.button === 0) { // <- check that was left button or touch
console.log(view.zoom);
if (view.zoom > 10) { // <- zoom related condition to open popup
view.popup.open({ // <- open popup
location: event.mapPoint, // <- use map point of the click event
fetchFeatures: true // <- fetch the selected features (if any)
});
} else {
window.alert(`Popup display zoom lower than 10 .. Zoom in buddy! .. (Current zoom ${view.zoom})`);
}
}
});
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
Related to only display one result in the popup, you could hide the navigation like this,
view.popup.visibleElements.featureNavigation = false;
Now if what you actually want is to get only one result, then I suggest to use view method hitTest, that only gets the topmost result of the layers. You could do this after inside the click handler and only open if any result of desire layer. For this you need to set featFeatures: false, and set the features with the hit one.
Just as a comment it could result weird or confusing to the user retrieve just one of all possible features. I think probable you may have a problem with the content.

Related

I am trying to make an application that tracks multiple users

I am trying to make a application that tracks multiple people on Google maps and allows the user to see who he wants to track.
I would like this app to send the long and lat to mysql. I am having trouble trying to get the longitude and latitude of the user to update in mysql. What is the best way to to do this?
All i want to do is track multiple people and plot them on a user map, so if the user wanted to see where his friends where at it would show on his cell phone.
If you are using web, you can get each users location from the browser using geolocation:
http://www.w3schools.com/html/html5_geolocation.asp
Since you don't say what your app is written in though we cannot offer any more specific advice.
You will then need to upload that to your app and store it in the database along with a key identifying each user.
The client would then have to be able to pick which of these users they wish to view, at which point you would draw them on a map using something like Google Maps API:
https://developers.google.com/maps/
<!DOCTYPE html>
<html>
<!--
geoLocMap.html by Bill Weinman
<http://bw.org/contact/>
created 2011-07-07
updated 2011-07-20
Copyright (c) 2011 The BearHeart Group, LLC
This file may be used for personal educational purposes as needed.
Use for other purposes is granted provided that this notice is
retained and any changes made are clearly indicated as such.
-->
<head>
<title>
Geolocation Map Test (1.1.3)
</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#map_canvas { height: 100%; width: 100% }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script type="text/javascript">
var watchID;
var geo; // for the geolocation object
var map; // for the google map object
var mapMarker; // the google map marker object
// position options
var MAXIMUM_AGE = 200; // miliseconds
var TIMEOUT = 300000;
var HIGHACCURACY = true;
function getGeoLocation() {
try {
if( !! navigator.geolocation ) return navigator.geolocation;
else return undefined;
} catch(e) {
return undefined;
}
}
function show_map(position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
var latlng = new google.maps.LatLng(lat, lon);
if(map) {
map.panTo(latlng);
mapMarker.setPosition(latlng);
} else {
var myOptions = {
zoom: 18,
center: latlng,
// mapTypeID --
// ROADMAP displays the default road map view
// SATELLITE displays Google Earth satellite images
// HYBRID displays a mixture of normal and satellite views
// TERRAIN displays a physical map based on terrain information.
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
map.setTilt(0); // turns off the annoying default 45-deg view
mapMarker = new google.maps.Marker({
position: latlng,
title:"You are here."
});
mapMarker.setMap(map);
}
}
function geo_error(error) {
stopWatching();
switch(error.code) {
case error.TIMEOUT:
alert('Geolocation Timeout');
break;
case error.POSITION_UNAVAILABLE:
alert('Geolocation Position unavailable');
break;
case error.PERMISSION_DENIED:
alert('Geolocation Permission denied');
break;
default:
alert('Geolocation returned an unknown error code: ' + error.code);
}
}
function stopWatching() {
if(watchID) geo.clearWatch(watchID);
watchID = null;
}
function startWatching() {
watchID = geo.watchPosition(show_map, geo_error, {
enableHighAccuracy: HIGHACCURACY,
maximumAge: MAXIMUM_AGE,
timeout: TIMEOUT
});
}
window.onload = function() {
if((geo = getGeoLocation())) {
startWatching();
} else {
alert('Geolocation`enter code here` not supported.')
}
}
</script>
</head>
<body>
<div id="map_canvas"></div>
</body>
</html>

How do I open links in jQuery server side Datatables through the jQuery ColorBox?

So basically I am using jQuery Datatables server-side functionality with PHP to retrieve a table with details from MySQL as illustrated here
From the HTML side, the following jQuery script (1) references the PHP script that grabs the data from MySQL and (2) then defines the table and customizes the columns in the row details.
My problem is getting the links in the row details to collaborate with ColorBox.
Here is the script I am using:
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
memTable = $('#members').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "detailsm.php",
"aoColumns": [
{ "sClass": "center", "bSortable": false },
null,
null,
null,
{ "sClass": "center" },
{ "sClass": "center" },
{ "sClass": "center" },
{ "sClass": "center" },
{ "sClass": "center" }
],
"aaSorting": [[1, 'desc']]
} );
$('#members tbody td img').live( 'click', function () {
var memTr = $(this).parents('tr')[0];
if ( memTable.fnIsOpen(memTr) )
{
/* This row is already open - close it */
this.src = "datatables/details_open.png";
memTable.fnClose( memTr );
}
else
{
/* Open this row */
this.src = "datatables/details_close.png";
memTable.fnOpen( memTr, fnFormatMemberDetails(memTr), 'details' );
}
} );
} );
var memTable;
/* Formating function for row details */
function fnFormatMemberDetails ( memTr )
{
var mData = memTable.fnGetData( memTr );
var smOut = '<table cellpadding="2" cellspacing="0" border="0" style="padding-left:20px;">';
smOut += '<tr><td><b>Member Functions:</b></td><td></td><td><b>Details:</b></td><td></td></tr>';
smOut += '<tr><td><a class="iframesmall" href="changecontact.php?userid='+mData[1]+'&fn=chusr">Update Info</a></td><td><a class="iframe" href="notifymember.php?memberid='+mData[1]+'">Notify</a></td>'
+'<td>Full Name: '+mData[14]+' '+mData[3]+'</td><td>Category: '+mData[11]+' | Created by: '+mData[12]+'</td></tr>';
smOut += '<tr><td><a class="iframe" href="renewmember.php?memberid='+mData[1]+'">Renew Subscription</a></td><td><a class="iframe" href="rp.php?memberid='+mData[1]+'">Reset Password</a></td> <td>Address: '+mData[15]+', '+mData[16] +', '+mData[17]+'</td><td>Mobile: '+mData[18]+'</td></tr>';
smOut += '<tr><td><a class="iframe" href="disactivatemember.php?memberid='+mData[1]+'">Disactivate</a></td><td><a class="iframe" href="deletemember.php?memberid='+mData[1]+'">Delete</a></td> <td>Last Login: '+mData[10]+ '</td><td>Last Updated: '+mData[13]+'</td></tr>';
smOut += '</table>';
return smOut;
}
</script>
My ColorBox jquery script defines the class iframesmall, which is referenced above in the fnFormatMemberDetails function that formats row details for the jquery data table.
Here is the part of the code from fnFormatMemberDetails that formats my row details as you can see above:
smOut += '<tr><td><a class="iframesmall" href="changecontact.php?userid='+mData[1]+'&fn=chusr">Update Info</a></td><td><a class="iframesmall" href="notifymember.php?memberid='+mData[1]+'">Notify</a></td>'
+'<td>Full Name: '+mData[14]+' '+mData[3]+'</td><td>Category: '+mData[11]+' | Created by: '+mData[12]+'</td></tr>';
And here is my jQuery ColorBox script, which works on the same page when called through regular HTML (but not through HTML output via jQuery/javascript):
<link rel="stylesheet" href="colorbox/colorbox.css" />
<script src="colorbox/jquery.colorbox.js"></script>
<script>
$(document).ready(function(){
//Examples of how to assign the ColorBox event to elements
$(".photogall").colorbox({rel:'photogall'});
$(".photothumbs").colorbox({rel:'photothumbs'});
$(".iframesmall").colorbox({iframe:true, width:"800px", height:"80%"});
});
</script>
To sum it up: How do I get ColorBox to work with html links that are generated via jQuery/javascript? All suggestions are welcome. Thank you.
Simply reapply colorbox() after you add the elements dinamicallhy
else
{
/* Open this row */
this.src = "datatables/details_close.png";
//here you add the data
memTable.fnOpen( memTr, fnFormatMemberDetails(memTr), 'details' );
//here you should add colorbox for the newly added elements
$(".iframesmall").colorbox({iframe:true, width:"800px", height:"80%"});
}
How do I get ColorBox to work with html links that are generated via jQuery/javascript?
Assign or re-assign colorbox after you have generated those links.

dojox.charting.Chart dataRange not restricting the chart x axis properly

I am building an application that monitors the number of services running on an application server. Information about the services running will be stored on a database, and I want to display some of that information on a webpage. At this point I just want to build a graphical representation of the number of services actively running, which updates dynamically as the database is updated. The goal is to create a simple chart that displays the most recent 10 (or so) values for the number of services running, similar to what an ekg readout looks like. I am using the dojox.charting.Chart widget, but I am having trouble updating the chart properly, so that it only displays the ten most recent values for numFailedAttempts:"0". As it is right now, the chart displays all the values, and the x axis values continuously get closer and closer together to accommidate everything. Based on the dojo api reference and documentation on dojotoolkit.org, I thought that the "displayRange" attribute for the dojox.charting.Chart was supposed to solve this problem. So my question is, what am I doing wrong? Here's the code:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/resources/dojo.css">
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.6.0/dojo/dojo.xd.js" data-dojo-config="isDebug: true, parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojox.charting.StoreSeries");
dojo.require("dojox.charting.Chart2D");
dojo.require("dojo.store.Memory");
dojo.require("dojo.store.Observable");
dojo.require("dojox.charting.Chart");
dojo.require("dojox.charting.plot2d.Areas");
dojo.ready(function(){renderDataChart()});
function renderDataChart(){
//data from a database
var dataChartData = {
itentifier: 'id',
items:
[
{id: 1, serviceName:"service1", startDate:"today", endDate:"today", numFailedAttempts:"1", errorTime:"null", errorMessage:"null", suppressError:"null"},
{id: 2, serviceName:"service2", startDate:"today", endDate:"today", numFailedAttempts:"1", errorTime:"now", errorMessage:"broken", suppressError:"click"},
{id: 3, serviceName:"service3", startDate:"today", endDate:"today", numFailedAttempts:"0", errorTime:"now", errorMessage:"broken", suppressError:"click"},
{id: 4, serviceName:"service4", startDate:"today", endDate:"today", numFailedAttempts:"1", errorTime:"now", errorMessage:"broken", suppressError:"click"},
{id: 5, serviceName:"service5", startDate:"today", endDate:"today", numFailedAttempts:"0", errorTime:"null", errorMessage:"null", suppressError:"null"}
]
};
//data store
var dataChartStore = dojo.store.Observable(new dojo.store.Memory({
data: {
identifier: "id",
label: "runningServices",
items: dataChartData
}
}));
var dataChart = new dojox.charting.Chart("myDataChart", {
displayRange: 10,
stretchToFit: false,
scrolling: true,
fieldName: "runningServices",
type: dojox.charting.plot2d.Areas
});
dataChart.addAxis("x", {microTickStep: 1, minorTickStep: 1});
dataChart.addAxis("y", {vertical: true, minorTickStep: 1, natural: true});
dataChart.addSeries("y", new dojox.charting.StoreSeries(dataChartStore, {query: {numFailedAttempts: 0}}, "value"));
dataChart.render();
//update datastore to simulate new data
var startNumber = dataChartData.length;
var interval = setInterval(function(){
dataChartStore.notify({value: Math.ceil(Math.random()*29), id: ++startNumber, numFailedAttempts: 0});
}, 1000);
}
</script>
</head>
<body>
<div id="myDataChart" style="width: 500px; height: 200px;"></div>
</body>
I have been struggling with the same issue. I have not completely figured it out, but I have found an alternative that does what I think you are describing. Here is the code (explanation below):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/resources/dojo.css">
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.6.0/dojo/dojo.xd.js" data-dojo-config="isDebug: true, parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojox.charting.StoreSeries");
dojo.require("dojo.store.Memory");
dojo.require("dojo.store.Observable");
dojo.require("dojox.charting.Chart2D");
dojo.require("dojox.charting.Chart");
dojo.require("dojox.charting.plot2d.Areas");
dojo.ready(function () {
renderArrayChart();
renderStoreChart();
});
function renderArrayChart() {
try {
var dataChart = new dojox.charting.Chart("myArrayChart", {
stretchToFit: false,
scrolling: false,
type: dojox.charting.plot2d.Areas,
title: "update array, rerender"
});
// create an array of x/y pairs as the data source
var data = [{ x: 1, y: 2.1}];
dataChart.addAxis("x", { microTickStep: 1, minorTickStep: 1 });
// set min/max so the Y axis scale does not change with the data
dataChart.addAxis("y", { vertical: true, minorTickStep: 1, natural: true, min: 0, max: 30 });
// create the series with the data array as the source
dataChart.addSeries("y", data);
dataChart.render();
// this counter is used as the x value for new data points
var startNumber = data.length;
//update datastore to simulate new data
var interval = setInterval(function () {
// if we have more than 9 data points in the array, remove the first one
if (data.length > 9) data.splice(0, 1);
// push a new data point onto the array using the counter as the X value
data.push({ x: ++startNumber, y: Math.ceil(Math.random() * 29) });
// update the series with the updated arrray
dataChart.updateSeries("y", data);
// re-render the chart
dataChart.render();
}, 1000);
}
catch (ex) {
alert(ex.message);
}
}
function renderStoreChart() {
try {
// create an array as the data source
var dataArray = [{ id: 1, value: 2.1}];
// create the observable data store
var dataStore = dojo.store.Observable(new dojo.store.Memory({
data: {
identifier: "id",
items: dataArray
}
}));
var storeChart = new dojox.charting.Chart("myStoreChart", {
stretchToFit: false,
scrolling: false,
type: dojox.charting.plot2d.Areas,
title: "data store"
});
storeChart.addAxis("x", { microTickStep: 1, minorTickStep: 1 });
// set min/max so the Y axis scale does not change with the data
storeChart.addAxis("y", { vertical: true, minorTickStep: 1, natural: true, min: 0, max: 30 });
storeChart.addSeries("y", new dojox.charting.StoreSeries(dataStore, { bindings: { x: "id", y: "value"} }));
storeChart.render();
// this counter is used as the x value for new data points
var startNumber = 1;
//update datastore to simulate new data
var interval = setInterval(function () {
// if we have more than the desired number data points in the store, remove the first one
if (startNumber > 9) dataStore.notify(null, startNumber - 10);
// add a new point to the data store
dataStore.notify({ id: ++startNumber, value: Math.ceil(Math.random() * 29) });
}, 1000);
}
catch (ex) {
alert(ex.message);
}
}
</script>
</head>
<body>
<div id="myArrayChart" style="width: 500px; height: 200px;"></div><br />
<div id="myStoreChart" style="width: 500px; height: 200px;"></div>
</body>
</html>
The top chart uses a simple array as the data source (instead of an Observable store). In the interval function, it simply slices the first array element (after reaching the desired number of elements) and adds a new element. It then updates the series (dataChart.updateSeries) and then re-renders the chart. In order to get the X axis labels to work correctly, each array item is an object x and y value (e.g. {x: 1, y: 2.1}).
The bottom chart uses the data store (an adaptation of your example). It does get the data to scroll off the chart. The dataStore.notify(null, objectId) method will remove the object with the given id from the data store. However, the X axis labels on this chart still do not display correctly.
In either case, the chart does not scale well. Even with only about 50 data points, the rendering gets very slow. I may try looking at other options, such as Flot - which seems to perform better with a larger number of data points.

Dojo setQuery() on DataGrid - all items disappear?

I've racked my brain and done tons of research and testing and can't figure out what is going on.
I have a Dojo datagrid which is declared statically with some HTML. Using the GUI, my users will add items to the DataGrid, which works as it should. However, I'd like to have a function that is called at a certain point that uses Dojo's setQuery to filter the data that shows in the DataGrid. The problem is that once I run the setQuery command, ALL of the data in the grid disappears, no matter if it matches the query or not!
Here is some sample code:
var layoutItems = [[
{
field: "id",
name: "ID",
width: '5px',
hidden: true
},
{
field: "color",
name: "Color",
width: '80px'
}
]];
// Create an empty datastore //
var storeData = {
identifier: 'id',
label: 'id',
items: []
}
var store3 = new dojo.data.ItemFileWriteStore( {data : storeData} );
...
<div id="grid" dojoType="dojox.grid.DataGrid" jsId="grid5" store="store3" structure="layoutItems" queryOptions="{deep:true}" query="{}" rowsPerPage="40"></div>
...
function filterGrid() {
dijit.byId("grid").setQuery({color:"Red"});
}
....
function addItemToGrid(formdata) {
var jsonobj = eval("(" + dojo.toJson(formData, true) + ")");
var myNewItem = {
id: transactionItemID,
color: jsonobj.color
};
// Insert the new item into the store:
store3.newItem(myNewItem);
store3.save({onComplete: savecomplete, onError: saveerror});
}
Managed to fix it by running the a grid FILTER instead of setQuery periodically in the background with the help of some jQuery (not sure if setQuery would have worked as well, I don't really know the difference between the filter and setQuery, but filter is doing what I need it to do).
Here is some sample code; hope this helps someone else having problems with this:
// ADD JQUERY
<script src="http://code.jquery.com/jquery-latest.js"></script>
.
// PUT THIS IN THE <HEAD> OF THE PAGE
<script type="text/javascript">
$(document).ready(function() {
function filterTheDataGrid() {
if (dijit.byId("grid") != undefined) {
dijit.byId("grid").filter({color: "Red"});
}
}
// RUN THE filterTheDataGrid FUNCTION EVERY ONE SECOND (1000 MILLISECONDS) //
// LOWER '1000' FOR FASTER REFRESHING, MAYBE TO 500 FOR EVERY 0.5 SECOND REFRESHES //
var refreshDataGrid = setInterval(function() { filterTheDataGrid(); }, 1000);
}
</script>
.
// PUT THIS IN THE <HEAD> OF THE PAGE
<script type="text/javascript">
// SETUP THE LAYOUT FOR THE DATA //
var layoutItems = [[
{
field: "id",
name: "ID",
width: '5px',
hidden: true
},
{
field: "color",
name: "Color",
width: '80px'
}
]];
// Create an empty datastore //
var storeData = {
identifier: 'id',
label: 'id',
items: []
}
var store3 = new dojo.data.ItemFileWriteStore( {data : storeData} );
</script>
.
// PUT THIS IN THE <HTML> OF THE PAGE
<div id="grid" dojoType="dojox.grid.DataGrid" jsId="grid5" store="store3" structure="layoutItems" query="{ type: '*' }" clientSort="true" rowsPerPage="40"></div>
.
<script type="text/javascript">
function addItemToGrid(formdata) {
// THIS FUNCTION IS CALLED BY A DIALOG BOX AND GETS FORM DATA PASSED TO IT //
var jsonobj = eval("(" + dojo.toJson(formData, true) + ")");
var myNewItem = {
id: transactionItemID,
color: jsonobj.color
};
// Insert the new item into the store:
store3.newItem(myNewItem);
store3.save({onComplete: savecomplete, onError: saveerror});
}
</script>
Here is another option that I came up with, so that the filter is not running unnecessarily every x milliseconds; this basically uses JavaScript to make a new setInterval which runs once after 500 milliseconds and then does a clearInterval so that it doesn't run again. Looks like just calling the filterTheDataGrids() function after adding an item won't do.. we have to delay for a split second and then call it:
// PUT THIS IN THE <HEAD> OF THE PAGE
<script type="text/javascript">
// Declare the global variables
var refreshDataGrid;
var refreshDataGridInterval = 500; // Change this as necessary to control how long to wait before refreshing the Data Grids after an item is added or removed.
</script>
.
// PUT THIS IN THE <HEAD> OF THE PAGE
<script type="text/javascript">
function filterTheDataGrids() {
if (dijit.byId("grid") != undefined) {
dijit.byId("grid").filter({color: "Red"});
}
clearInterval (refreshDataGrid); // Running the filter just once should be fine; if the filter runs too quickly, then make the global refreshDataGridInterval variable larger
}
</script>
.
// PUT THIS IN THE <HEAD> OF THE PAGE
<script type="text/javascript">
// SETUP THE LAYOUT FOR THE DATA //
var layoutItems = [[
{
field: "id",
name: "ID",
width: '5px',
hidden: true
},
{
field: "color",
name: "Color",
width: '80px'
}
]];
// Create an empty datastore //
var storeData = {
identifier: 'id',
label: 'id',
items: []
}
var store3 = new dojo.data.ItemFileWriteStore( {data : storeData} );
</script>
.
// PUT THIS IN THE <HTML> OF THE PAGE
<div id="grid" dojoType="dojox.grid.DataGrid" jsId="grid5" store="store3" structure="layoutItems" query="{ type: '*' }" clientSort="true" rowsPerPage="40"></div>
.
<script type="text/javascript">
function addItemToGrid(formdata) {
// THIS FUNCTION IS CALLED BY A DIALOG BOX AND GETS FORM DATA PASSED TO IT //
var jsonobj = eval("(" + dojo.toJson(formData, true) + ")");
var myNewItem = {
id: transactionItemID,
color: jsonobj.color
};
// Insert the new item into the store:
store3.newItem(myNewItem);
store3.save({onComplete: savecomplete, onError: saveerror});
// Create setInterval on the filterTheDataGrids function; since simple calling the function won't do; seems to call it too fast or something
refreshDataGrid = setInterval(function() { filterTheDataGrids(); }, refreshDataGridInterval);
}
</script>

How to refilter a dojo DataGrid?

I have a DataGrid that I already filtered using grid.filter(query, rerender). If I add another item, after calling save() I see the new item in the grid even though it shouldn't display because of the filter. I'm thinking "ok, I'll just filter it again when the store finishes saving. But after calling grid.filter with the same query all the rows disappear. Any ideas what I might be doing wrong?
Code to filter the grid:
var filterQuery = dijit.byId("filterTextbox").attr("value");
var grid = dijit.byId("grid");
var queryValue = "*";
if(filterQuery != ""){
queryValue += filterQuery + "*";
}
grid.filter({name: queryValue}, true);
Code to add new items to the grid
function addItemToGrid(newItemName){
var newItem = {name: newItemName};
var grid = dijit.byId("grid");
var store = grid.store;
store.addItem(newItem);
store.save();
}
Try to use:
store.newItem(newItem);
instead of store.addItem(newItem);
(addItem is not a standard method to add items into store)
Inside of your addItemToGrid function, try adding an onComplete listener to your save method and sort or filter the grid in the onComplete function
store.save({onComplete: function() {
grid.filter({name: queryValue}, true);
}
});
I had the same problem and only managed to fix it by running the grid filter periodically in the background with the help of some jQuery. Here is some sample code; hope this helps someone else having problems with this.
// ADD JQUERY
<script src="http://code.jquery.com/jquery-latest.js"></script>
.
// PUT THIS IN THE <HEAD> OF THE PAGE
<script type="text/javascript">
$(document).ready(function() {
function filterTheDataGrid() {
if (dijit.byId("grid") != undefined) {
dijit.byId("grid").filter({color: "Red"});
}
}
// RUN THE filterTheDataGrid FUNCTION EVERY ONE SECOND (1000 MILLISECONDS) //
// LOWER '1000' FOR FASTER REFRESHING, MAYBE TO 500 FOR EVERY 0.5 SECOND REFRESHES //
var refreshDataGrid = setInterval(function() { filterTheDataGrid(); }, 1000);
}
</script>
.
// PUT THIS IN THE <HEAD> OF THE PAGE
<script type="text/javascript">
// SETUP THE LAYOUT FOR THE DATA //
var layoutItems = [[
{
field: "id",
name: "ID",
width: '5px',
hidden: true
},
{
field: "color",
name: "Color",
width: '80px'
}
]];
// Create an empty datastore //
var storeData = {
identifier: 'id',
label: 'id',
items: []
}
var store3 = new dojo.data.ItemFileWriteStore( {data : storeData} );
</script>
.
// PUT THIS IN THE <HTML> OF THE PAGE
<div id="grid" dojoType="dojox.grid.DataGrid" jsId="grid5" store="store3" structure="layoutItems" query="{ type: '*' }" clientSort="true" rowsPerPage="40"></div>
.
<script type="text/javascript">
function addItemToGrid(formdata) {
// THIS FUNCTION IS CALLED BY A DIALOG BOX AND GETS FORM DATA PASSED TO IT //
var jsonobj = eval("(" + dojo.toJson(formData, true) + ")");
var myNewItem = {
id: transactionItemID,
color: jsonobj.color
};
// Insert the new item into the store:
store3.newItem(myNewItem);
store3.save({onComplete: savecomplete, onError: saveerror});
}
</script>