Select to view content in your preferred language

Application with Editor Widget and TypeScript - automatically fill the input fields of the editor widget with the address information from the locator

1742
4
Jump to solution
10-28-2023 10:04 AM
Den-GIS
Occasional Contributor

Hello everyone,

I'm trying to automatically fill the input fields of Editor Widget with the address information. I use the locator to get the address and lat/long. The editor widget and locator work well separately in the application. All my previous attempts to add the results from the locator into the input fields of the form template of the editor widget have failed. My problem is that I cannot transfer the results from the locator to the ExpressionInfos and then further into the Field Elements.
I looked at the following examples e.g. (Editing with calculated field expressions | Sample Code | ArcGIS Maps SDK for JavaScript 4.28 | ArcG..., Edit features with the Editor widget | Sample Code | ArcGIS Maps SDK for JavaScript 4.28 | ArcGIS De...). Does anyone have any idea how can I solve this problem? I am very grateful for every hint!
Here is my code:

import MapView from "esri/views/MapView";
import EsriMap from "esri/Map";
import FeatureLayer from "esri/layers/FeatureLayer";
import Basemap from "esri/Basemap";
import VectorTileLayer from "esri/layers/VectorTileLayer";
import Editor from 'esri/widgets/Editor';
import FieldElement from 'esri/form/elements/FieldElement'
import FormTemplate from 'esri/form/FormTemplate'
import ExpressionInfo from 'esri/form/ExpressionInfo'
import locator from "esri/rest/locator";
 
 
const basemap = new Basemap({
  baseLayers: [
    new VectorTileLayer({
      url: osm
    })
  ],
  title: "Basemap",
  id: "basemap"
});

const map = new EsriMap({
  basemap: basemap
})
const view = new MapView({
  map: map,
  container: "viewDiv",
  center: [-78.50169, -0.21489],
  zoom: 12
});
 
/**############################### Editing Layer ################################# */
let accidentsPointLayer = new FeatureLayer({
  url: car_accidents,
  title: "Car accidents",
  visible: true,
  opacity: 1.0,
  popupTemplate: popupEditingLayers
})
 map.add(accidentsPointLayer);
// ##############  Locator  #########################


view.on("click"function (evt) {
    const params = {
        location: evt.mapPoint
    };

    locator.locationToAddress(serviceUrlparams).then(
        function (response) {
            const res = response;
            console.log(res);
            const house_number = response.attributes.AddNum;
            const street = response.attributes.Address;
            const city = response.attributes.City;
            const district = response.attributes.District;
            const postal_code = response.attributes.Postal;
            const lat = response.location.latitude;
            const long = response.location.longitude;
            showAddress(house_numberstreetcitydistrictpostal_codelatlong);
        }
    );
});

function showAddress(house_numberstringstreetstringcitystringdistrictstringpostal_codestringlatnumberlongnumber) {
    console.log(house_number);
    console.log(street);
    console.log(city);
    console.log(district);
    console.log(postal_code);
    console.log (lat);
    console.log(long);

}

//  ExpressionInfos for the Form Template
const houseNumberExpression = new ExpressionInfo({
    expression: "",
    name: "house_number",
    title: "house_number",
    returnType: "string"
});
const streetExpression = new ExpressionInfo({
    expression: "",
    name: "street",
    title: "street",
    returnType: "string"
});

const cityExpression = new ExpressionInfo({
    expression: "",
    name: "city",
    title: "city",
    returnType: "string"
});
const districtExpression = new ExpressionInfo({
    expression: "",
    name: "district",
    title: "district",
    returnType: "string"
});
const postalCodeExpression = new ExpressionInfo({
    expression: "",
    name: "postal_code",
    title: "postal_code",
    returnType: "string"
});
const latExpression = new ExpressionInfo({
    expression: "",
    name: "latitude",
    title: "latitude",
    returnType: "number"
});
const longExpression = new ExpressionInfo({
    expression: "",
    name: "longitude",
    title: "longitude",
    returnType: "number"
});

// Field Elements for the Feature Form
const fieldElement1 = new FieldElement({
    fieldName: "houseNR",
    label: "House Number",
    valueExpression: ''
});
const fieldElement2 = new FieldElement({
    fieldName: "street",
    label: "Street",
    valueExpression: ''
});
const fieldElement3 = new FieldElement({
    fieldName: "city",
    label: "City",
    valueExpression: ''
});
const fieldElement4 = new FieldElement({
    fieldName: "district",
    label: "District"
});
const fieldElement5 = new FieldElement({
    fieldName: "postalCode",
    label: "Postal Code"
});
const fieldElement6 = new FieldElement({
    fieldName: "lat",
    label: "X"
});
const fieldElement7 = new FieldElement({
    fieldName: "long",
    label: "Y"
});

const addressformTemplate = new FormTemplate({
    title: "Data editing",
    description: "Please enter all relevant information in the fields provided below",
    elements: [fieldElement1fieldElement2fieldElement3fieldElement4fieldElement5fieldElement6fieldElement7],
    expressionInfos: [houseNumberExpressionstreetExpressioncityExpressiondistrictExpressionpostalCodeExpressionlatExpressionlongExpression ]
});

viewMap.when(() => {

    viewMap.map.editableLayers.forEach((layer=> {
        if (layer.type === "feature" && layer.title === "Car accidents") {
            layer.formTemplate = addressformTemplate;
        }
    });

    const editor = new Editor({
        view: viewMap,
        container: document.getElementById("editor")
    });
    viewMap.ui.add("panelContent""manual")
})
Spoiler
 
0 Kudos
1 Solution

Accepted Solutions
Den-GIS
Occasional Contributor

So, after taking a few days to read all the ArcGIS JS API documentation regarding the Editor Widget, Sketch Widget, Feature Form Widget, Feaure Templates and all their view models, methods and events, in the end I succeeded. If anyone else wants to use this advanced functionality of the Editor Widget (version ArcGIS JS API 4.28) (in the web app builder as part of the Smart Editor Widget), here is the code. I hope that this self-understanding functionality will be implemented as a standard "property" in the editor widget at some point. When new features are recorded, in addition to special data, the address, coordinates and date are usually recorded. Nowadays, app users expect that when they create a new object, they don't at least have to type in the address. By the way, this reduces typing errors and data administration. That's why I needed it and was important to me to implement. As I said, I hope this functionality will come standard in the next versions of the ArcGIS JS API. Nevertheless, I would like to give a lot of praise to the ESRI ArcGIS JS API development team because they always leave a “way” open to implement the desired functionality themselves if necessary, even if it is painful for days. 👏😊

viewMap.when(() => {

     // Create the Editor
    const editor = new Editor({
        view: viewMap,
        container: document.getElementById("editor")
    });
    // Starts monitoring when the user has clicked Feature Template in Editor Widget to draw (add) a new object to the map.
    editor.viewModel.featureTemplatesViewModel.on("select", (evtTemplate=> {
       // Get the current date and time for the date field (UTC time)
        const datetime = Date.now();
        // Monitoring when the sketch widget has started drawing the object
        editor.viewModel.sketchViewModel.on("create"function (event) {
            // When the drawing has reached the status of "complete", get the geometry
            if (event.state === "complete") {
                let geom = event.graphic.geometry;
                //If the drawing is of type "polyline" or "polygon" get the coordinates (Point) from the center of the geometry. 
                //The point is required as a parameter for the locator
                if (geom.type === "polyline" || geom.type === "polygon") {
                    let center = geom.extent.center;
                    console.log(center);
                    const params = {
                        location: center
                    };
                    // Get the address using the locator
                    locator.locationToAddress(locatorServiceURLparams).then(
                        function (response) {
                            const res = response;
                            const house_number = response.attributes.AddNum;
                            const street = response.attributes.Address;
                            const city = response.attributes.City;
                            const district = response.attributes.District;
                            const postal_code = response.attributes.Postal;
                            const lat = response.location.latitude;
                            const long = response.location.longitude;

                            //With the method setValue() of the FeatureFormViewModel, 
                            //the results from the locator are added to the attribute fields (feature form) of the editor widget
                            editor.viewModel.featureFormViewModel.setValue('city'city);
                            editor.viewModel.featureFormViewModel.setValue('district'district)
                            editor.viewModel.featureFormViewModel.setValue('street'street);
                            editor.viewModel.featureFormViewModel.setValue('houseNr'house_number);
                            editor.viewModel.featureFormViewModel.setValue('date'datetime);
                        }
                    );

                } else if (geom.type === "point") {
                    //If the drawing is of type "point" create (Point) from the geometry and pass it to Locator. 
                    let point = new Point(geom);
                    const params = {
                        location: point
                    };
                    locator.locationToAddress(locatorServiceURLparams).then(
                        function (response) {
                            const res = response;
                            console.log(res);
                            const house_number = response.attributes.AddNum;
                            const street = response.attributes.Address;
                            const city = response.attributes.City;
                            const district = response.attributes.District;
                            const postal_code = response.attributes.Postal;
                            const lat = response.location.latitude;
                            const long = response.location.longitude;

                            editor.viewModel.featureFormViewModel.setValue('city'city);
                            editor.viewModel.featureFormViewModel.setValue('district'district)
                            editor.viewModel.featureFormViewModel.setValue('street'street);
                            editor.viewModel.featureFormViewModel.setValue('houseNr'house_number);
                            editor.viewModel.featureFormViewModel.setValue('date'datetime);
                            editor.viewModel.featureFormViewModel.setValue('lat'lat);
                            editor.viewModel.featureFormViewModel.setValue('long'long);
                        }
                    );
                }
            }
        });

    });
})

View solution in original post

4 Replies
Den-GIS
Occasional Contributor

So, after taking a few days to read all the ArcGIS JS API documentation regarding the Editor Widget, Sketch Widget, Feature Form Widget, Feaure Templates and all their view models, methods and events, in the end I succeeded. If anyone else wants to use this advanced functionality of the Editor Widget (version ArcGIS JS API 4.28) (in the web app builder as part of the Smart Editor Widget), here is the code. I hope that this self-understanding functionality will be implemented as a standard "property" in the editor widget at some point. When new features are recorded, in addition to special data, the address, coordinates and date are usually recorded. Nowadays, app users expect that when they create a new object, they don't at least have to type in the address. By the way, this reduces typing errors and data administration. That's why I needed it and was important to me to implement. As I said, I hope this functionality will come standard in the next versions of the ArcGIS JS API. Nevertheless, I would like to give a lot of praise to the ESRI ArcGIS JS API development team because they always leave a “way” open to implement the desired functionality themselves if necessary, even if it is painful for days. 👏😊

viewMap.when(() => {

     // Create the Editor
    const editor = new Editor({
        view: viewMap,
        container: document.getElementById("editor")
    });
    // Starts monitoring when the user has clicked Feature Template in Editor Widget to draw (add) a new object to the map.
    editor.viewModel.featureTemplatesViewModel.on("select", (evtTemplate=> {
       // Get the current date and time for the date field (UTC time)
        const datetime = Date.now();
        // Monitoring when the sketch widget has started drawing the object
        editor.viewModel.sketchViewModel.on("create"function (event) {
            // When the drawing has reached the status of "complete", get the geometry
            if (event.state === "complete") {
                let geom = event.graphic.geometry;
                //If the drawing is of type "polyline" or "polygon" get the coordinates (Point) from the center of the geometry. 
                //The point is required as a parameter for the locator
                if (geom.type === "polyline" || geom.type === "polygon") {
                    let center = geom.extent.center;
                    console.log(center);
                    const params = {
                        location: center
                    };
                    // Get the address using the locator
                    locator.locationToAddress(locatorServiceURLparams).then(
                        function (response) {
                            const res = response;
                            const house_number = response.attributes.AddNum;
                            const street = response.attributes.Address;
                            const city = response.attributes.City;
                            const district = response.attributes.District;
                            const postal_code = response.attributes.Postal;
                            const lat = response.location.latitude;
                            const long = response.location.longitude;

                            //With the method setValue() of the FeatureFormViewModel, 
                            //the results from the locator are added to the attribute fields (feature form) of the editor widget
                            editor.viewModel.featureFormViewModel.setValue('city'city);
                            editor.viewModel.featureFormViewModel.setValue('district'district)
                            editor.viewModel.featureFormViewModel.setValue('street'street);
                            editor.viewModel.featureFormViewModel.setValue('houseNr'house_number);
                            editor.viewModel.featureFormViewModel.setValue('date'datetime);
                        }
                    );

                } else if (geom.type === "point") {
                    //If the drawing is of type "point" create (Point) from the geometry and pass it to Locator. 
                    let point = new Point(geom);
                    const params = {
                        location: point
                    };
                    locator.locationToAddress(locatorServiceURLparams).then(
                        function (response) {
                            const res = response;
                            console.log(res);
                            const house_number = response.attributes.AddNum;
                            const street = response.attributes.Address;
                            const city = response.attributes.City;
                            const district = response.attributes.District;
                            const postal_code = response.attributes.Postal;
                            const lat = response.location.latitude;
                            const long = response.location.longitude;

                            editor.viewModel.featureFormViewModel.setValue('city'city);
                            editor.viewModel.featureFormViewModel.setValue('district'district)
                            editor.viewModel.featureFormViewModel.setValue('street'street);
                            editor.viewModel.featureFormViewModel.setValue('houseNr'house_number);
                            editor.viewModel.featureFormViewModel.setValue('date'datetime);
                            editor.viewModel.featureFormViewModel.setValue('lat'lat);
                            editor.viewModel.featureFormViewModel.setValue('long'long);
                        }
                    );
                }
            }
        });

    });
})
BlakeTerhune
MVP Regular Contributor

I really appreciate you posting the solution when you found it. Many people don't, and it's a shame. Could you format the code in a code block?

Den-GIS
Occasional Contributor

Yes I agree with you. here is the codepen ArcGIS Maps SDK for JS - Editor Widget with Locator (codepen.io)

0 Kudos
DavinShokes1
Occasional Contributor II

Thank you for this sample @Den-GIS.  I had a similar app need that would pull locator data based on the users address search. The features are created client side and displayed via popup. After seeing your sample, I might switch from a popup to a featureformviewmodel to allow for additional user input. Here is the code pen if it helps anyone. https://codepen.io/Treemapper/pen/abMgLNW 

0 Kudos