Edit/Update features Offline using JavaScript

725
0
07-08-2019 07:13 AM
DharminNaik
New Contributor

Hello All,

I am stuck at this,

I want to include Offline map in my website which is in PHP and Its having Html Page.
In Html Page i have Included Arcgis Map and also its providing Edit functionality from there only. 
But i want to include Offline edit functionality too. so, that whenever internet goes off still user can edit feature and store them in local storage and then whenever internet come back, it will update data to Server. 


I tried so many examples but none of them worked for me.

Here is my html code 

f
<html>

<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<!--
ArcGIS API for JavaScript, https://js.arcgis.com
For more information about the editing-groupedfeatureform sample, read the original sample description at developers.arcgis.com.
https://developers.arcgis.com/javascript/latest/sample-code/editing-groupedfeatureform/index.html
-->
<title>Update Feature Attributes - 4.12</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.28/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.28/esri/css/esri.css">

<link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.12/"></script>
<script src="http://localhost/offline-master/offline.min.js"></script>
<script src="offline.js"></script>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}

#info {
padding: 14px;
border-radius: 5px;
}

#update {
padding: 6px;
}

#form {
background: #fff;
}

/* replaces esri-widget--panel */
.scroller {
overflow-x: hidden;
overflow-y: auto;
}
</style>
<!-- <script src="https://js.arcgis.com/3.28/"></script> -->
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/FeatureForm",
"esri/layers/FeatureLayer",
"dojo/domReady!",
"dojo/_base/json",
"esri/symbols/Symbol",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol",
"dojo/DeferredList"
], function (Map, MapView, FeatureForm, FeatureLayer, dojo, Symbol, SimpleMarkerSymbol, SimpleLineSymbol, DeferredList) {
let highlight, editFeature;
//var map;
// var featureLayer;
// if (window.localStorage.getItem("storedCollection")) {
// debugger
// console.log('Feature Collection read from storage');
// addLayer(dojo.fromJson(window.localStorage.getItem("storedCollection")));
// } else {
// debugger
// // var mapserverUrl = "https://services5.arcgis.com/lVkj5PBOw7tRmIPU/arcgis/rest/services/Notes/FeatureServer/1";
// var mapserverUrl = "https://services6.arcgis.com/b2FEzOrGRpJ07dgO/arcgis/rest/services/trailheads/FeatureServer/0";
// var deferred = getLayerResource(mapserverUrl);

// deferred.then(function (response) {
// var featureCollection = {};
// featureCollection.layerDefinition = response;

// var fields = dojo.map(featureCollection.layerDefinition.fields, function (field) {
// return dojo.mixin({
// editable: true,
// domain: null
// }, field);
// });

// featureCollection.layerDefinition.fields = fields;

// window.localStorage.setItem("storedCollection", dojo.toJson(featureCollection));
// console.log("Feature Collection added to storage");
// console.log(featureCollection);
// addLayer(featureCollection);
// });
// }
var trailheadsRenderer = {
"type": "simple",
"symbol": {
"type": "simple-marker",
"color": "#f70233",
//"url": "http://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png",
"width": "10px",
"height": "10px"
}
}

// Add labels
var trailheadsLabels = {
symbol: {
type: "text",
color: "#FFFFFF",
haloColor: "#5E8D74",
haloSize: "2px",
font: {
size: "12px",
family: "Noto Sans",
style: "italic",
weight: "normal"
}
},
labelPlacement: "above-center",
labelExpressionInfo: {
expression: "$feature.TRL_NAME"
}
};

// Add parks with a class breaks renderer and unique symbols
function createFillSymbol(value, color) {
alert(value);
alert(color);
return {
"value": value,
"symbol": {
"color": color,
"type": "simple-marker",
"style": "circle",
"outline": {
"style": "none"
}
},
"label": value
};
}

// var openSpacesRenderer = {
// // type: "unique-value",
// type: "simple",
// field: "TRL_NAME",
// uniqueValueInfos: [
// createFillSymbol("Backbone Trail", "#f70511"),
// createFillSymbol("Deer Valley Loop Trail", "#0025fa"),
// createFillSymbol("Zuma Canyon Trail", "#00fa08"),
// createFillSymbol("Crags Road", "#fad900")
// ]
// };

const featureLayer = new FeatureLayer({
portalItem: {
//id: "449887ea7d60429fbf6f0c67881f2758"
id: "bbae7e54e7704feaaaf2353d6aa3209c"
//id: "6ebfb46b4ba4455383f01ad4d04aa143"
},
renderer: trailheadsRenderer,
// renderer: openSpacesRenderer,
labelingInfo: [trailheadsLabels],
opacity: 1.0
});

const map = new Map({
basemap: "topo",
layers: [featureLayer]
});

let view = new MapView({
map: map,
container: "viewDiv",
center: [-118.7524793, 34.11303909],
zoom: 12
});

// Add a new feature form with grouped fields
const form = new FeatureForm({
container: "form",
//groupDisplay: "sequential", // only display one group at a time
layer: featureLayer,
fieldConfig: [
{
// autocastable to FieldGroupConfig
label: "Inspector information", // Inspector group
description: "Field inspector information",
// individual field configurations within the group
fieldConfig: [
{
// autocastable as FieldConfig
name: "TRL_NAME",
label: "TRL_NAME"
}
]
}
]
});

// Disable popup
view.popup.autoOpenEnabled = false;
//init();
debugger
view.on("click", function (event) {
// Unselect any currently selected features
unselectFeature();

if (navigator.onLine != false) {
OfflineProcess();
}

// Listen for when the user clicks on the view
view.hitTest(event).then(function (response) {
// If user selects a feature, select it
const results = response.results;
debugger
if (
results.length > 0 &&
results[0].graphic &&
results[0].graphic.layer === featureLayer
) {
selectFeature(
results[0].graphic.attributes[featureLayer.objectIdField]
);
} else {
// Hide the form and show the info div
document.getElementById("update").classList.add("esri-hidden");
}
});
});

// function getLayerResource(url) {
// var deferred = esri.request({
// url: url,
// content: {
// f: 'json'
// },
// callbackParamName: "callback"
// });
// return deferred;
// }

// function initEditor(results) {
// var featureLayerInfos = dojo.map(results, function (result) {
// return {
// 'featureLayer': result.layer
// };
// });
// featureLayer = results[0].layer;
// var settings = {
// map: map,
// layerInfos: featureLayerInfos
// };

// var params = {
// settings: settings
// };
// var editorWidget = new esri.dijit.editing.Editor(params, 'editorDiv');
// editorWidget.startup();
// map.infoWindow.resize(290, 220);
// }

// function saveCollection() {
// //save the edited features to local storage
// console.log('Edits saved to storage');
// console.log(featureLayer.toJson());
// window.localStorage.setItem("storedCollection", dojo.toJson(featureLayer.toJson()));
// }

// Function to unselect features
function unselectFeature() {
debugger
if (highlight) {
highlight.remove();
}
}

// Highlight the clicked feature and display
// its attributes in the featureform.
function selectFeature(objectId) {
// query feature from the server
featureLayer
.queryFeatures({
objectIds: [objectId],
outFields: ["*"],
returnGeometry: true
})
.then(function (results) {
debugger
if (results.features.length > 0) {
editFeature = results.features[0];

// display the attributes of selected feature in the form
form.feature = editFeature;

// highlight the feature on the view
view.whenLayerView(editFeature.layer).then(function (layerView) {
highlight = layerView.highlight(editFeature);
});

if (
document
.getElementById("update")
.classList.contains("esri-hidden")
) {
document.getElementById("info").classList.add("esri-hidden");
document
.getElementById("update")
.classList.remove("esri-hidden");
}
}
});
}

// Listen to the feature form's submit event.
form.on("submit", function () {
debugger
if (editFeature) {
// Grab updated attributes from the form.
const updated = form.getValues();

// Loop through updated attributes and assign
// the updated values to feature attributes.
Object.keys(updated).forEach(function (name) {
editFeature.attributes[name] = updated[name];
});

// Setup the applyEdits parameter with updates.
const edits = {
updateFeatures: [editFeature]
};
applyAttributeUpdates(edits);
}
});

// Call FeatureLayer.applyEdits() with specified params.
function applyAttributeUpdates(params) {
debugger
document.getElementById("btnUpdate").style.cursor = "progress";
featureLayer
.applyEdits(params)
.then(function (editsResult) {
// Get the objectId of the newly added feature.
// Call selectFeature function to highlight the new feature.
if (editsResult.addFeatureResults.length > 0) {
const objectId = editsResult.addFeatureResults[0].objectId;
selectFeature(objectId);
}
document.getElementById("btnUpdate").style.cursor = "pointer";
})
.catch(function (error) {
console.log("===============================================");
console.error(
"[ applyEdits ] FAILURE: ",
error.code,
error.name,
error.message
);
console.log("error = ", error);
document.getElementById("btnUpdate").style.cursor = "pointer";
});
}

document.getElementById("btnUpdate").onclick = function () {
// Fires feature form's submit event.
form.submit();
};

view.ui.add("update", "top-right");
view.ui.add("info", {
position: "top-left",
index: 1
});
});
</script>
</head>

<body>
<div id="viewDiv"></div>
<div id="info" class="esri-widget">
<h3>Select a feature to begin editing</h3>
</div>

<div id="update" class="esri-widget esri-hidden">
<div id="form" class="scroller esri-component"></div>
<input type="button" class="esri-button" value="Update assessment" id="btnUpdate" />
</div>
</body>

</html>

can anyone help me out with this if it is possible? 

I want to do it by JavaScript only. 

0 Kudos
0 Replies