<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="https://www.w3.org/2005/Atom">
  <channel>
    <title>Arcgis on Josh Werts</title>
    <link>https://joshwerts.com/tags/arcgis/</link>
    <description>Recent content in Arcgis on Josh Werts</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 23 Mar 2018 13:41:03 -0400</lastBuildDate>
    <atom:link href="https://joshwerts.com/tags/arcgis/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Monkey-patching the ESRI JSAPI to mock services</title>
      <link>https://joshwerts.com/blog/2018/03/23/monkey-patching-the-esri-jsapi-to-mock-services/</link>
      <pubDate>Fri, 23 Mar 2018 13:41:03 -0400</pubDate>
      
      <guid>https://joshwerts.com/blog/2018/03/23/monkey-patching-the-esri-jsapi-to-mock-services/</guid>
      <description>

&lt;p&gt;Lately I&amp;rsquo;ve been working on a project where I&amp;rsquo;m unable to access the client&amp;rsquo;s ArcGIS Server services
directly and don&amp;rsquo;t have the data/environment to publish locally.  Working directly on the server is slow and I wanted a way to mock in a few services just to get started on some UI elements.  There are some online services that help w/ mocking HTTP calls, but I didn&amp;rsquo;t really want to put the data out there in the cloud&amp;hellip;.&lt;/p&gt;

&lt;p&gt;So how about some &lt;strong&gt;monkey-patching&lt;/strong&gt;?&lt;/p&gt;

&lt;h3 id=&#34;concept:58365f17369855609e8a0624874f7e55&#34;&gt;Concept&lt;/h3&gt;

&lt;p&gt;Here&amp;rsquo;s the basic concept - since nothing is really closed in JavaScript, we can intercept global functions, perform some action and then allow the function to continue as usual.  Here&amp;rsquo;s a simple example - let&amp;rsquo;s say we want to log the url of all XHR requests to the console:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// place this anonymous closure somewhere in your code before any service calls.
// could be in a script tag in index.html for instance.
(function (open) {

  // REPLACE the open function with a new function
  XMLHttpRequest.prototype.open = function (method, url, async, user, password) {

    // log out the url
    console.log(&#39;XHR request to: &#39;, url);

    // after we do our work, call the ORIGINAL open function so we continue normally.
    open.apply(this, arguments);
  };

  // pass the ORIGINAL function in as a parameter.
})(XMLHttpRequest.prototype.open);

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Example output in Chrome console:&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&#34;https://joshwerts.com/img/xhr_logging.png&#34; alt=&#34;XHR logging in chrome console&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;featurelayer-xhr-example:58365f17369855609e8a0624874f7e55&#34;&gt;FeatureLayer (XHR) Example&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Some&lt;/em&gt; of the JSAPI uses XHR to pass queries.  For instance, this is an example of intercepting and mocking out service calls from a JSAPI 4.6 FeatureLayer.  In this case, we&amp;rsquo;re just checking the URL on each call and changing it to our JSON (which is simply previous ArcGIS Server calls saved out into .json files).  There are 3 steps here based on how ESRI has implemented the FeatureLayer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the FeatureLayer is instantiated, a call is made to the endpoint w/ &lt;code&gt;f=json&lt;/code&gt; to retrieve the service&amp;rsquo;s schema.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;At 4.x ESRI performs a &lt;code&gt;returnCountOnly&lt;/code&gt; call to get the total count of features.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Then, the API tries to iterate through the objectIds with actual query calls to get all of the features, but we&amp;rsquo;re just returning a single response.  There&amp;rsquo;s a major gotcha here:  Make sure &lt;code&gt;&amp;quot;exceededTransferLimit&amp;quot;: false&lt;/code&gt; is set to &lt;code&gt;false&lt;/code&gt; in the json or the API will just keep iterating indefinitely trying to get all of the features.&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;(function (open) {
  XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
    if (url === &#39;https://server/arcgis/rest/services/myservice/MapServer/5?f=json&#39;) {
      console.log(&#39;open&#39;, method, url, async, user, password);
      url = &#39;https://localhost:8080/app/mocks/ags/my_ags_service_info.json&#39;;
    }

    if (url.indexOf(&#39;https://server/arcgis/rest/services/myservice/MapServer/5/query&#39;) &amp;gt; -1) {
      if (url.indexOf(&#39;returnCountOnly&#39;) &amp;gt; -1) {
        console.log(&#39;open&#39;, method, url, async, user, password);
        url = &#39;https://localhost:8080/app/mocks/ags/my_ags_service_5_values_count.json&#39;;
      } else {
        console.log(&#39;open&#39;, method, url, async, user, password);
        url = &#39;https://localhost:8080/app/mocks/ags/my_ags_service_5_values.json&#39;;
      }
    }
    open.apply(this, arguments);
  };
})(XMLHttpRequest.prototype.open);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;querytask-jsonp-example:58365f17369855609e8a0624874f7e55&#34;&gt;QueryTask (jsonp) Example&lt;/h3&gt;

&lt;p&gt;Other parts of the API use jsonp instead of XHR to handle requests so we can&amp;rsquo;t intercept via XMLHttpRequest.  Here&amp;rsquo;s a slightly different approach to handle a &lt;code&gt;QueryTask.execute&lt;/code&gt; call by patching the class&amp;rsquo;s &lt;code&gt;execute&lt;/code&gt; function itself.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// NOTE: requires here are with a Webpack setup.
import QueryTask = require(&#39;esri/tasks/QueryTask&#39;);
import Point = require(&#39;esri/geometry/Point&#39;);
import FeatureSet = require(&#39;esri/tasks/support/FeatureSet&#39;);
import esriRequest = require(&#39;esri/request&#39;);

(function (execute) {
  QueryTask.prototype.execute = function (query, requestOptions?) {
    if (this.url.indexOf(&#39;https://server/arcgis/rest/services/myservice/MapServer/5?f=json&#39;) &amp;gt; -1) {

      // create a new Promise and do our own call to the local mocked json response.
      return new Promise((resolve, reject) =&amp;gt; {
        esriRequest(&#39;https://localhost:8080/app/mocks/ags/my_features.json&#39;).then(response =&amp;gt; {
          let featureSet = new FeatureSet(response.data);

          // In some cases geometries weren&#39;t correctly created and needed to fix.
          for (let f of featureSet.features) {
            f.geometry = new Point({
              x: f.geometry.x,
              y: f.geometry.y,
              spatialReference: {
                wkid: 4326
              }
            });
          }
          // resolve the promise with our mocked FeatureSet
          resolve(featureSet);
        }, error =&amp;gt; reject(error));
      });
    }
  }
  return execute.apply(this, arguments);
})(QueryTask.prototype.execute);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are probably better ways to accomplish this and I definitely wouldn&amp;rsquo;t suggest doing anything like this for a production app, but it can still be useful in some cases.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Group by query in a file geodatabase</title>
      <link>https://joshwerts.com/blog/2018/01/16/group-by-query-in-a-file-geodatabase/</link>
      <pubDate>Tue, 16 Jan 2018 13:51:36 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2018/01/16/group-by-query-in-a-file-geodatabase/</guid>
      <description>&lt;p&gt;File geodatabase feature classes and tables lack some of the more advanced ability to query that a true relational database supports.  Sometimes these queries can be simulated with arcpy cursors; one good example is a SQL group by query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical SQL&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT field, count(*) from table group by field order by count(*) desc;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;In arcpy&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;from collections import Counter

def group_by_count(table_or_fc, fields):
    &amp;quot;&amp;quot;&amp;quot; Returns dictionary containing count of unique items &amp;quot;&amp;quot;&amp;quot;
    counter = Counter()
    with arcpy.da.SearchCursor(table_or_fc, fields) as curs:
        for row in curs:
            # no need to store as a tuple if only 1 field, just store the value
            if len(row) == 1:
                row = row[0]
            counter[row] += 1
    return counter


def group_by_count_formatted(table_or_fc, fields):
    &amp;quot;&amp;quot;&amp;quot; prints out counts of unique values &amp;quot;&amp;quot;&amp;quot;
    counter = group_by_count(table_or_fc, fields)
    # sort yields highest count records first (order by count(*) desc)
    for key, count in sorted(counter.items(), reverse=True, key=lambda item: item[1]):
        print(&amp;quot;{}: {:,}&amp;quot;.format(str(key), count))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Example usage in ArcMap Python console (single field)&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;&amp;gt;&amp;gt;&amp;gt; group_by_count(&#39;junctions&#39;, &#39;ImpedanceType&#39;)
Counter({u&#39;SmallStreet&#39;: 455145, u&#39;LargeStreet&#39;: 28714, u&#39;Stream&#39;: 9375, u&#39;RailRoad&#39;: 1742})

&amp;gt;&amp;gt;&amp;gt; group_by_count_formatted(&#39;junctions&#39;, &#39;ImpedanceType&#39;)
SmallStreet: 455,145
LargeStreet: 28,714
Stream: 9,375
RailRoad: 1,742
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Example usage in ArcMap Python console (multiple fields)&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;&amp;gt;&amp;gt;&amp;gt; group_by_count(&#39;junctions&#39;, [&#39;ImpedanceType&#39;, &#39;InfrastructureType&#39;])
Counter({(&#39;SmallStreet&#39;, &#39;New&#39;): 318834, (&#39;LargeStreet&#39;, &#39;New&#39;): 28710, (&#39;Stream&#39;, &#39;New&#39;): 18379, (&#39;Stream&#39;, &#39;Aerial&#39;): 5806, (&#39;RailRoad&#39;, &#39;New&#39;): 4043, (&#39;Stream&#39;, &#39;Underground&#39;): 3227, (&#39;RailRoad&#39;, &#39;Aerial&#39;): 1035, (&#39;RailRoad&#39;, &#39;Underground&#39;): 668})

&amp;gt;&amp;gt;&amp;gt; group_by_count_formatted(&#39;junctions&#39;, [&#39;ImpedanceType&#39;, &#39;InfrastructureType&#39;])
(&#39;SmallStreet&#39;, &#39;New&#39;): 318,834
(&#39;LargeStreet&#39;, &#39;New&#39;): 28,710
(&#39;Stream&#39;, &#39;New&#39;): 18,379
(&#39;Stream&#39;, &#39;Aerial&#39;): 5,806
(&#39;RailRoad&#39;, &#39;New&#39;): 4,043
(&#39;Stream&#39;, &#39;Underground&#39;): 3,227
(&#39;RailRoad&#39;, &#39;Aerial&#39;): 1,035
(&#39;RailRoad&#39;, &#39;Underground&#39;): 668
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These functions aren&amp;rsquo;t going to be as efficient as a SQL query, but they can be quite useful sometimes for ad-hoc data exploration - especially in the Arcmap/Pro console.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ESRI Javascript API 4 with Angular 2 - Transition to Webpack</title>
      <link>https://joshwerts.com/blog/2017/01/08/esri-javascript-api-4-with-angular-2---transition-to-webpack/</link>
      <pubDate>Sun, 08 Jan 2017 14:21:52 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2017/01/08/esri-javascript-api-4-with-angular-2---transition-to-webpack/</guid>
      <description>&lt;p&gt;Since my &lt;a href=&#34;https://joshwerts.com/blog/2016/05/17/esri-javascript-api-4-with-angular-2-and-typescript/&#34;&gt;first post&lt;/a&gt; on Angular 2 and the ESRI API, I&amp;rsquo;ve transitioned from SystemJS to Webpack which I&amp;rsquo;m enjoying thoroughly.&lt;/p&gt;

&lt;p&gt;Sample App w/ Webpack setup:&lt;br /&gt;
&lt;strong&gt;&lt;a href=&#34;https://joshwerts.com/angular2-esri-play&#34;&gt;Demo&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;&lt;a href=&#34;https://github.com/jwerts/angular2-esri-play&#34;&gt;Repo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IMO, Webpack has a few major advantages over SystemJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development build step is much faster and lite-server does not bog down with memory leaks (not sure why that happened with the SystemJS setup but lite-server got slower and slower until restarted).&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Webpack takes care of bundling code for you (everything expect the ESRI requires).&lt;br /&gt;

&lt;ul&gt;
&lt;li&gt;This setup also bundles each components&amp;rsquo; html and css in the main bundle.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Feels like less of a hack to use with esri - simply require in each module and that&amp;rsquo;s it.  Setup is simply specifying ESRI as an &amp;ldquo;external&amp;rdquo;.  Nothing really special there and it just works.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;No need for a grunt/gulp step to minimize, etc.  Webpack is pretty comprehensive.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This app is just a map with a custom coordinate display component (bottom left):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://joshwerts.com/img/map_w_coordinates.png&#34; alt=&#34;Coordinate component&#34; /&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve used a similar webpack configuration to this in a couple production apps over the last several months.  Unit testing w/ this setup and Typescript is finally starting to feel natural (instead of a large very verbose burden w/ es5).  I&amp;rsquo;ve found it fairly straightfoward to test domain classes and models w/ business logic where I feel you get the most bang for your buck from testing.  What I haven&amp;rsquo;t quite figured out yet is how to test components (and when it&amp;rsquo;s actually worth the effort).  This project contains a working test for the coordinate component&amp;hellip;  It works, but I&amp;rsquo;m not yet convinced it&amp;rsquo;s the best way to go about it.  Please comment if you have experience here!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coordinate Component test&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { TestBed, ComponentFixture } from &#39;@angular/core/testing&#39;;
import { DebugElement } from &#39;@angular/core&#39;;

import { CoordinateComponent } from &#39;./coordinate.component&#39;;

let fixture: ComponentFixture&amp;lt;CoordinateComponent&amp;gt;;
let component: CoordinateComponent;
let de: DebugElement;
let el: HTMLElement;
let $mapDiv;
let mapDivEl: Element;
beforeEach(() =&amp;gt; {
  // refine the test module by declaring the test component
  TestBed.configureTestingModule({
    declarations: [CoordinateComponent]
  });

  // create component and test fixture
  fixture = TestBed.createComponent(CoordinateComponent);
  el = fixture.nativeElement;

  // get test component from the fixture
  component = fixture.componentInstance;

  // add a div to the body
  $mapDiv = $(&#39;&amp;lt;div&amp;gt;&#39;, { id: &#39;mapDiv&#39; }).appendTo(&#39;body&#39;);
  mapDivEl = $mapDiv[0];

  // mock required MapView props/functions
  component.mapView = &amp;lt;any&amp;gt;{
    container: mapDivEl,
    toMap: (point) =&amp;gt; {
      return {
        longitude: 5,
        latitude: 10
      };
    },
    zoom: 7,
    scale: 500
  };

  // runs ngOnInit
  fixture.detectChanges();
});

describe(&#39;Coordinate&#39;, () =&amp;gt; {
  it(&#39;should update lat/long on mousemove&#39;, () =&amp;gt; {
    mapDivEl.dispatchEvent(new Event(&#39;mousemove&#39;, {
      bubbles: true,
      cancelable: true
    }));
    // pageX, pageY
    fixture.detectChanges();
    expect(el.querySelector(&#39;#longitude&#39;).innerHTML).toBe(&#39;5.000000&#39;);
    expect(el.querySelector(&#39;#latitude&#39;).innerHTML).toBe(&#39;10.000000&#39;);
    expect(el.querySelector(&#39;#zoom&#39;).innerHTML).toBe(&#39;7&#39;);
    expect(el.querySelector(&#39;#scale&#39;).innerHTML).toBe(&#39;500&#39;);
  });
});
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Fun with Python Sets (and arcpy)</title>
      <link>https://joshwerts.com/blog/2016/07/21/fun-with-python-sets-and-arcpy/</link>
      <pubDate>Thu, 21 Jul 2016 17:38:05 -0400</pubDate>
      
      <guid>https://joshwerts.com/blog/2016/07/21/fun-with-python-sets-and-arcpy/</guid>
      <description>&lt;p&gt;I often forget about the Python &lt;code&gt;set&lt;/code&gt;, so this is a fun reminder to myself to keep it in mind.  Here&amp;rsquo;s a neat example of using a set for deleting fields.&lt;/p&gt;

&lt;p&gt;This function deletes all of the fields &lt;em&gt;except&lt;/em&gt; the ones you specify:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def delete_all_fields_except(fc, keep_fields):
    &amp;quot;&amp;quot;&amp;quot; deletes all fields except those specfied as keep_fields &amp;quot;&amp;quot;&amp;quot; 
    # create set of all possible fields but exclude OBJECTID, SHAPE, etc.
    all_fields = set(f.name for f in arcpy.ListFields(fc) if not f.required)

    # get a list of fields in the featureclass but not in the list of fields to keep
    # using set.difference()
    
    delete_fields = list(all_fields.difference(keep_fields))
    
    # delete out all the fields
    arcpy.management.DeleteField(fc, delete_fields)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# Assume our feature class has the following fields:
print([f.name for f in arcpy.ListFields(fc)])
# [&#39;OBJECTID&#39;, &#39;Shape&#39;, &#39;field1&#39;, &#39;field2&#39;, &#39;field3&#39;, &#39;field4&#39;, &#39;field5&#39;]

keep_fields = [&#39;field1&#39;, &#39;field3&#39;]
delete_all_fields_except(fc, keep_fields)

print([f.name for f in arcpy.ListFields(fc)])
# [&#39;OBJECTID&#39;, &#39;Shape&#39;, &#39;field1&#39;, &#39;field3&#39;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is pretty simple example and you could obviously accomplish this without using set, but set is more elegant and more efficient (probably doesn&amp;rsquo;t matter much here).  Perhaps I&amp;rsquo;ll update this post with more advanced usage now that this is here to remind me to think about sets!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ESRI Javascript API 4 with Angular 2 and Typescript</title>
      <link>https://joshwerts.com/blog/2016/05/17/esri-javascript-api-4-with-angular-2-and-typescript/</link>
      <pubDate>Tue, 17 May 2016 20:23:08 -0400</pubDate>
      
      <guid>https://joshwerts.com/blog/2016/05/17/esri-javascript-api-4-with-angular-2-and-typescript/</guid>
      <description>

&lt;p&gt;&lt;strong&gt;Update 1/8/2017: &lt;/strong&gt;I&amp;rsquo;ve transitioned to Webpack since this post: &lt;a href=&#34;https://joshwerts.com/blog/2017/01/08/esri-javascript-api-4-with-angular-2---transition-to-webpack/&#34;&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This could really be a post about many things.&lt;/p&gt;

&lt;p&gt;First, I&amp;rsquo;m a believer in client-side MV*.  Second, I&amp;rsquo;m trying to incorporate better testing into my front-end JS code.  Angular seemed like a natural fit given these 2 primary objectives.  I&amp;rsquo;ve done a fair amount of work now with Angular 1 and the ESRI JSAPI 3.x library.  There have been some solid success here, but Dojo &lt;code&gt;require&lt;/code&gt; throughout the app and especially in unit tests have been a major headache.  You could perhaps mock all dependencies from ESRI in the unit tests or try to keep ESRI in it&amp;rsquo;s own untested sandbox, but both of these strategies seems better in theory than practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aside&lt;/strong&gt;: ESRI does not make any of this easy.  Sure, you can get it to work&amp;hellip; kind of&amp;hellip;. with a lot of headaches along the way.  It all boils down to Dojo.  Don&amp;rsquo;t get me wrong, the ESRI API does some amazing things and some of the new 4.0 features look incredibly promising (&lt;code&gt;.watch()&lt;/code&gt; is brilliant), but there&amp;rsquo;s really no solid reason why we&amp;rsquo;re still forced to use Dojo.&lt;/p&gt;

&lt;p&gt;Anyway, getting to what this post is really about&amp;hellip;.&lt;/p&gt;

&lt;h2 id=&#34;the-app:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;The App&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://joshwerts.com/jsapi4-angular2&#34; target=&#34;_blank&#34; ____&gt;&lt;img src=&#34;https://joshwerts.com/img/jsapi4ang2_tests_liteserver_app.png&#34; alt=&#34;Full setup&#34; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://joshwerts.com/jsapi4-angular2/&#34;&gt;Live Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From a high level view, the app simply adds points to the map and shows a list of those points with their geometry and &amp;ldquo;index&amp;rdquo; attribute.  Nothing too special - just there to test some concepts.  As an added bonus, the app is served through lite-server and constantly updates as you code.  Similarly, the unit tests run continuously.&lt;/p&gt;

&lt;p&gt;Building upon experimental work by &lt;a href=&#34;https://github.com/odoe/esrijs4-vm-angular2&#34;&gt;Rene Rubalcava&lt;/a&gt; and &lt;a href=&#34;https://github.com/tomwayson/angular2-esri-example&#34;&gt;Tom Wayson&lt;/a&gt;, I was able to get an Angular 2 app properly loading dojo dependencies both in the browser and in Karma tests.&lt;/p&gt;

&lt;p&gt;The app consists of a &amp;ldquo;model&amp;rdquo; (Angular service) to hold the points (or domain object of your choosing) - the thought being that business logic in this model would be testable without being concerned about the objects&amp;rsquo; relation to the map.  Ideally, this model wouldn&amp;rsquo;t contain ESRI dependencies, but with the JSAPI 4&amp;rsquo;s watch capabilities, it seems to make sense to use an &lt;code&gt;esri/core/Collection&lt;/code&gt; as the underlying data structure in the model.  Also ideally, we&amp;rsquo;d just have the collection in the model, but it seems the only way to achieve the map automagically updating is if we use the points from a GraphicsLayer (passing in our Collection as the graphics property to the GraphicsLayer constructor worked in 4.0beta3, but not in 4.0 final for some reason).&lt;/p&gt;

&lt;h3 id=&#34;pointsmodel-points-model-ts:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;PointsModel (points.model.ts)&lt;/h3&gt;

&lt;p&gt;So here&amp;rsquo;s our PointsModel (in Typescript).  We&amp;rsquo;ve simply wrapped a few &lt;code&gt;Collection&lt;/code&gt; methods and then we can add some additional business logic like &lt;code&gt;getIndexSum()&lt;/code&gt;.  &lt;code&gt;index&lt;/code&gt; is just a made up attribute for sake of testing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { Injectable } from &#39;@angular/core&#39;;

import Graphic from &#39;esri/Graphic&#39;;
import GraphicsLayer from &#39;esri/layers/GraphicsLayer&#39;;
import Collection from &#39;esri/core/Collection&#39;;

@Injectable()
export class PointsModel {
  private points: Collection = new Collection();
  pointsLayer: GraphicsLayer;
  constructor() {
    this.pointsLayer = new GraphicsLayer();
    this.points = this.pointsLayer.graphics;
  }
  addPoint(pointGraphic: Graphic) {
    this.points.add(pointGraphic);
  }
  addPoints(pointsGraphics: Graphic[]) {
    this.points.addMany(pointsGraphics);
  }
  getPointGraphics() {
    return this.points;
  }
  clear() {
    this.points.removeAll();
  }
  getIndexSum() {
    let sum = 0;
    if (this.points !== null) {
      this.points.forEach(p =&amp;gt; sum += p.attributes.index);
    }
    return sum;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;attributecomponent-attribute-component-html:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;AttributeComponent (attribute.component.html)&lt;/h3&gt;

&lt;p&gt;When we add a point to the model, it not only shows up in the map, but also in the attribute list which is wired up through databinding:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;div&amp;gt;
  &amp;lt;h2&amp;gt;Points!&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;Index Sum: {{pointsModel.getIndexSum()}}
  &amp;lt;ul&amp;gt;
    &amp;lt;li *ngFor=&amp;quot;let point of points.toArray()&amp;quot;&amp;gt;
      &amp;lt;span&amp;gt;{{point.attributes.index}} ({{point.geometry.x | number:&#39;.5-5&#39;}},{{point.geometry.y | number:&#39;.5-5&#39;}})&amp;lt;/span&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;mapservice-map-service-ts:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;MapService (map.service.ts)&lt;/h3&gt;

&lt;p&gt;Our map binding to our PointsModel (which is just a matter of adding pointsModel.pointsLayer (our GraphicsLayer) to the map):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { Injectable } from &#39;@angular/core&#39;;

import Map from &#39;esri/Map&#39;;
import GraphicsLayer from &#39;esri/layers/GraphicsLayer&#39;;

import { PointsModel } from &#39;./points.model&#39;;

@Injectable()
export class MapService {
  map: Map;
  pointGraphicsLayer: GraphicsLayer;
  constructor(pointsModel: PointsModel) {
    this.map = new Map({
      basemap: &#39;topo&#39;
    });
    this.map.add(pointsModel.pointsLayer);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;pointsmodel-tests-points-model-spec-ts:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;PointsModel Tests (points.model.spec.ts)&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { PointsModel } from &#39;./points.model&#39;;

import Graphic from &#39;esri/Graphic&#39;;
import Point from &#39;esri/geometry/Point&#39;;

describe(&#39;PointsModel tests&#39;, () =&amp;gt; {
  let mockPointGraphic = new Graphic({
    attributes: {
      index: 1
    },
    geometry: new Point({
      x: 1,
      y: 2,
      spatialReference: {
        wkid: 4326
      }
    })
  });

  let pointsModel;
  beforeEach(() =&amp;gt; {
    pointsModel = new PointsModel();
  });

  it(&#39;should contstruct it&#39;, () =&amp;gt; {
    expect(pointsModel).toBeDefined();
    expect(pointsModel.getPointGraphics()).toBeDefined();
  });

  describe(&#39;adding and removing points&#39;, () =&amp;gt; {
    it(&#39;should add a point to collection&#39;, () =&amp;gt; {
       pointsModel.addPoint(mockPointGraphic);
       pointsModel.addPoint(mockPointGraphic);
       expect(pointsModel.getPointGraphics().length).toEqual(2);
    });

    it(&#39;should add points to collection&#39;, () =&amp;gt; {
      pointsModel.addPoints([mockPointGraphic, mockPointGraphic]);
      expect(pointsModel.getPointGraphics().length).toEqual(2);
    });

    it(&#39;should clear points&#39;, () =&amp;gt; {
      pointsModel.addPoint(mockPointGraphic);
      pointsModel.addPoint(mockPointGraphic);
      pointsModel.clear();
      expect(pointsModel.getPointGraphics().length).toEqual(0);
    });
  });

  describe(&#39;calculations&#39;, () =&amp;gt; {
    it(&#39;should calculate the sum of the index attributes&#39;, () =&amp;gt; {
      pointsModel.addPoints([mockPointGraphic, mockPointGraphic]);
      let sum = pointsModel.getIndexSum();
      expect(sum).toEqual(2);
    });
  });

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The nice thing here is that the tests didn&amp;rsquo;t balk at using the esri &lt;code&gt;Collection&lt;/code&gt; that must be imported into the PointsModel (&lt;strong&gt;this has been an incredibly difficult thing to do w/ Angular 1 / Dojo&lt;/strong&gt;).&lt;/p&gt;

&lt;h2 id=&#34;setup:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;Setup&lt;/h2&gt;

&lt;p&gt;Setup for this is non-trivial and is based heavily on &lt;a href=&#34;https://github.com/Esri/esri-system-js&#34;&gt;esri/esri-system-js&lt;/a&gt; along with custom configuration in the Karma configuration and loading of dependencies locally using the &lt;a href=&#34;https://github.com/Esri/arcgis-js-api&#34;&gt;esri bower jsapi repo&lt;/a&gt;.  In short, the esri-system-js loader loads &lt;strong&gt;ALL&lt;/strong&gt; esri dependencies at the start of the application so they&amp;rsquo;re available through import statements in Typescript files.  This was already figured out for the browser portion by Tom and Rene as referenced previously, so check out their repo&amp;rsquo;s for more information there.&lt;/p&gt;

&lt;p&gt;Getting it wired up for testing was a little more difficult but here are the key highlights.  Note that I&amp;rsquo;ve broken out some different configs for browser vs tests.&lt;/p&gt;

&lt;h3 id=&#34;dojoconfigtest-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;dojoConfigTest.js&lt;/h3&gt;

&lt;p&gt;Fairly standard setup for loading from a &lt;strong&gt;local&lt;/strong&gt; bower setup.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;(function(window) {
  // set up your dojoConfig
  window.dojoConfig = {
    baseUrl: &#39;app/node_modules/&#39;,
    deps: [&#39;app/main&#39;],
    packages: [
      &#39;app&#39;,
      &#39;dijit&#39;,
      &#39;dojo&#39;,
      &#39;dojox&#39;,
      &#39;dstore&#39;,
      &#39;dgrid&#39;,
      &#39;esri&#39;, {
        name: &#39;moment&#39;,
        location: &#39;moment&#39;,
        main: &#39;moment&#39;
      }
    ]
  };
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;karma-conf-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;karma.conf.js&lt;/h3&gt;

&lt;p&gt;These are the changes that were added to the karma.conf.js configuration included in the &lt;a href=&#34;https://github.com/angular/quickstart&#34;&gt;angular2 quick start repo&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;  ...

  files: [
    ... angular files, etc.
    // ********* esri load ***********
    // must be able to serve these files for dojo require
    // NOTE: karma gives a cryptic error when 
    // files can&#39;t be found  (msg || &amp;quot;&amp;quot;).replace is not a function
    { pattern: &#39;bower_components/dojo/**/*.*&#39;, included: false, watched: false },
    { pattern: &#39;bower_components/dojox/**/*.*&#39;, included: false, watched: false },
    { pattern: &#39;bower_components/dstore/**/*.*&#39;, included: false, watched: false },     
    { pattern: &#39;bower_components/dgrid/**/*.*&#39;, included: false, watched: false },
    
    { pattern: &#39;bower_components/dijit/**/*.*&#39;, included: false, watched: false },
    { pattern: &#39;bower_components/esri/**/*.*&#39;, included: false, watched: false },    
    { pattern: &#39;bower_components/moment/**/*.js&#39;, included: false, watched: false },   

    // load dojoConfig so dojo knows where to &amp;quot;require&amp;quot; modules from
    &#39;dojoConfigTest.js&#39;,
    
    // we need the actual dojo startup file for &amp;quot;requrire&amp;quot; to be defined
    &#39;bower_components/dojo/dojo.js&#39;,
    
    // load in esri&#39;s systemJs util
    &#39;node_modules/esri-system-js/dist/esriSystem.js&#39;,
    
    // load in our array of esri dependencies
    &#39;esriLoadConfig.js&#39;,
    
    // bootstrap in the modules using esri-system-js
    &#39;esriSystemLoadTest.js&#39;, 

    ... more angular files
]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;esriloadconfig-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;esriLoadConfig.js&lt;/h3&gt;

&lt;p&gt;Contains &lt;strong&gt;ALL&lt;/strong&gt; esri modules required by the application:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;(function(window) {
  window.esriLoadConfig = {
      modules: [
      &#39;esri/Map&#39;,
      &#39;esri/views/MapView&#39;,
      &#39;esri/core/Collection&#39;,
      &#39;esri/layers/GraphicsLayer&#39;,
      &#39;esri/Graphic&#39;,
      &#39;esri/geometry/Point&#39;,
      &#39;esri/geometry/SpatialReference&#39;,
      &#39;esri/symbols/SimpleMarkerSymbol&#39;,
      &#39;esri/Color&#39;
    ]
  };
}(window))
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;esrisystemloadtest-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;esriSystemLoadTest.js&lt;/h3&gt;

&lt;p&gt;Called by Karma to pre-load the esri modules before the tests run.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// load esri modules needed by this application
// into a System.js module called esri
start = performance.now();
esriSystem.register(esriLoadConfig.modules, function () {
  end = performance.now();
  time = end - start;
  console.log(&#39;Loaded esri modules&#39;, time / 1000.0);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;esrisystemloadbrowser-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;esriSystemLoadBrowser.js&lt;/h3&gt;

&lt;p&gt;Used in the browser code (called from index.html) to load in the esri modules AND bootstrap the application once those modules are available.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// load esri modules needed by this application
// into a System.js module called esri
console.log(&amp;quot;Loading esri modules: &amp;quot;, esriLoadConfig.modules);
start = performance.now();
esriSystem.register(esriLoadConfig.modules, function () {
  // then bootstrap application
  end = performance.now();
  time = end - start;
  console.log(&#39;Loaded esri modules&#39;, time / 1000.0);
  System.import(&#39;app/main&#39;).then(function () {
    console.log(&#39;app/main imported&#39;);
  }, function (error) {
    console.log(&amp;quot;System import error:&amp;quot;, error);
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;conclusion:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;&lt;del&gt;This is &lt;strong&gt;highly experimental&lt;/strong&gt; and there&amp;rsquo;s &lt;strong&gt;a lot of moving parts&lt;/strong&gt;, but it&amp;rsquo;s nice to know this is possible.&lt;/del&gt; This is getting closer to production quality.  I&amp;rsquo;ve left out a lot but the full repo&amp;rsquo;s here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/jwerts/jsapi4-angular2&#34;&gt;https://github.com/jwerts/jsapi4-angular2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There will likely be updates to the repo as I continue to explore this concept (and learn Angular 2&amp;hellip; and learn Typescript).&lt;/p&gt;

&lt;p&gt;It could really benefit from a final build process.  Note that I&amp;rsquo;ve used CDN for most dependencies in index.html for the gh-pages demo to avoid loading local bower and node dependencies to Github.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit 2016-06-16:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0.RC2&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Edit 2016-06-24:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0.RC3&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Edit 2016-07-05:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0.RC4&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Edit 2016-07-07:&lt;/strong&gt; Updated to use &lt;strong&gt;esri-system-js 1.0 beta&lt;/strong&gt; which now preserves esri module names and works correctly with Typescript arcgis-js-api typings.&lt;br /&gt;
&lt;strong&gt;Edit 2016-09-22:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0 final&lt;/strong&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Feature Service applyEdits on Multiple Layers</title>
      <link>https://joshwerts.com/blog/2015/11/10/feature-service-applyedits-on-multiple-layers/</link>
      <pubDate>Tue, 10 Nov 2015 13:09:37 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2015/11/10/feature-service-applyedits-on-multiple-layers/</guid>
      <description>

&lt;p&gt;If you&amp;rsquo;ve worked with any of the esri web API&amp;rsquo;s over the last several years, chances are you&amp;rsquo;ve used a Feature Service to edit an SDE feature class at some point.  Using the web API&amp;rsquo;s, the obvious way to do this would be to construct a &lt;a href=&#34;https://developers.arcgis.com/javascript/jsapi/featurelayer-amd.html&#34;&gt;FeatureLayer&lt;/a&gt; and call its &lt;a href=&#34;https://developers.arcgis.com/javascript/jsapi/featurelayer-amd.html#applyedits&#34;&gt;applyEdits&lt;/a&gt; method.  In reality, this is just a wrapper around the ArcGIS Server REST API&amp;rsquo;s applyEdits endpoint on an individual service layer.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://[host]/arcgis/rest/services/[folder]/[service]/[layerid]/FeatureServer/applyEdits
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But what happens if you want to applyEdits to multiple layers within the Feature Service instead of just one layer?  You&amp;rsquo;ve got a few standard API options after constructing multiple feature layers:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Call applyEdits on each FeatureLayer with &lt;a href=&#34;https://dojotoolkit.org/api/?qs=1.10/dojo/promise/all&#34;&gt;dojo/promise/all&lt;/a&gt;:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// construct FeatureLayers
flayer1 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/0&amp;quot;);
flayer2 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/1&amp;quot;);

// call applyEdits
var deferred1 = flayer.applyEdits(adds1, deletes1, updates1);
var deferred2 = flayer.applyEdits(adds2, deletes2, updates2);

// use dojo/All to respond to success or failure when both operations finish
all([deferred1, deferred2]).then(function(results) {
  // Do something with results.
  // Note that you&#39;ll still need to check each edit in each layer for &amp;quot;success&amp;quot;
}, function(error) {
  // uh oh, one of them failed.  
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Chain promises for each FeatureLayer:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// construct FeatureLayers
flayer1 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/0&amp;quot;);
flayer2 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/1&amp;quot;);

// call applyEdits
flayer.applyEdits(adds1, deletes1, updates1).then(function(result1) {
  // do something with result
  // Note that you&#39;ll still need to check each edit for &amp;quot;success&amp;quot;
  flayer2.applyEdits(adds2, deletes2, updates2).then(function(result2) {
    // do something with result
    // Note that you&#39;ll still need to check each edit for &amp;quot;success&amp;quot;
  }, function(error) {
    // flayer 2 error
  });
}, function(error) {
  // flayer 1 error
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Either of these options would work, but what if the 2 layer edits depended on each other?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usually when I&amp;rsquo;m editing multiple layers at once, they have some sort of relation to each other.  This may or may not be defined in the database, but at any rate - if one edit fails, I&amp;rsquo;d really like the other edit to also fail so we don&amp;rsquo;t end up with an inconsistency in the database.  Additionally, wouldn&amp;rsquo;t it be nice to only send one request to the server, especially when there&amp;rsquo;s many layers?&lt;/p&gt;

&lt;h3 id=&#34;one-request-to-rule-them-all:49c8eba68da4672c57330404ff0b31cc&#34;&gt;One Request to Rule Them All&lt;/h3&gt;

&lt;p&gt;It turns out that the ArcGIS Server REST API also has an &lt;a href=&#34;https://resources.arcgis.com/en/help/rest/apiref/fsserviceedits.html&#34;&gt;applyEdits&lt;/a&gt; endpoint on the Feature Service itself - it&amp;rsquo;s just not wrapped in the web API&amp;rsquo;s.&lt;/p&gt;

&lt;p&gt;This makes it possible to send multiple edits in a single request AND make sure nothing gets stored on any layers if any one of the layer edits fails.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s nothing in the ESRI web API&amp;rsquo;s that directly hit this endpoint, so I give to you: FeatureService.js.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bower install featureservice-esri-jsapi
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;usage:49c8eba68da4672c57330404ff0b31cc&#34;&gt;Usage:&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;var package_path = window.location.pathname.substring(0, window.location.pathname.lastIndexOf(&#39;/&#39;));
var dojoConfig = {
  async: true,
  packages: [
    {
      name: &#39;feature-service&#39;,
      location: package_path + &#39;/js/lib/bower_components/featureservice-esri-jsapi/dist&#39;,
      main: &#39;FeatureService.min&#39;
    }
  ]
};

require(
  [
    &#39;feature-service&#39;
  ], function(FeatureService) {
    &#39;use strict&#39;;

    var service = new FeatureService(&amp;quot;https://[server]/arcgis/rest/MyService&amp;quot;);
    var edits = [
      {
        id: 2,  // id of layer in service
        adds: [
          addGraphic
        ],
        updates: [
          updateGraphic
        ],
        deletes: [
          1, 2  // just objectids of features to delete.
        ]
      },
      {
        id: 5,  // id of layer in service
        adds: [
          someGraphic,
          anotherGraphic,
          yetAnotherGraphic
        ]
      }
    ];

    var deferred = service.applyEdits(edits);
    deferred.then(function(result) {
      // result is an array
      // each array value contains an object with layer id and objectids of successful edits:
      /*
      [
        {
          id: int id of feature service layer
          adds: [oid, oid, oid, ...],
          updates: [oid, oid oid, ...],
          deletes: [oid, oid, oid, ...]
        },
        ...
      ]
      */
      // layer 2 results
      console.log(result[0].id);
      console.log(result[0].adds);
      console.log(result[0].updates);
      console.log(result[0].deletes);

      // layer 5 results
      console.log(result[1].id);
      console.log(result[1].adds);
      console.log(result[1].updates);
      console.log(result[1].deletes);

    }, function(error) {
      /* error callback can be called for 2 reasons
        1. Regular service faults (server 500 error, etc)
        2. One or more of the edits failed (but server still responded with 200)

        In case 1, the error is a standard esri error object with code and message.
        In case 2, the error is an object with code (200) and message plus an additional
        errors property which contains an array of error objects.
        Error object contains code, description, and id (layer id).
      */
      // case 2
      if (error.code === 200) {
        for (var i; i&amp;lt;error.errors.length; i++) {
          var err = error.errors[i];
          console.log(err.id);
          console.log(err.code);
          console.log(err.description);
        }
      }
    });
});

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Currently only the applyEdits endpoint is implemented, but this is really the most useful.  There are a couple of personal design decisions here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The service always sends rollbackOnFailure as true.  This seems to be the most likely use case.&lt;/li&gt;
&lt;li&gt;If any single edit fails, the fault handler is triggered.  This is different from the jsapi&amp;rsquo;s FeatureLayer, where even if there&amp;rsquo;s a failure, it will still trigger the success handler and you have to check each result for failures.  This class does it for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find this useful, please leave a comment or feel free to fork!&lt;br /&gt;
&lt;a href=&#34;https://github.com/jwerts/featureservice-esri-jsapi.git&#34;&gt;https://github.com/jwerts/featureservice-esri-jsapi.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a side note, this could have been a separate post on &lt;em&gt;&amp;ldquo;Unit testing esri Javascript API services with Karma/Mocha/Chai/Sinon&amp;rdquo;&lt;/em&gt;.  Perhaps in the future&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>arcpy: Reorder Fields</title>
      <link>https://joshwerts.com/blog/2014/04/17/arcpy-reorder-fields/</link>
      <pubDate>Thu, 17 Apr 2014 00:00:00 +0000</pubDate>
      
      <guid>https://joshwerts.com/blog/2014/04/17/arcpy-reorder-fields/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s another handy function for re-ordering fields in a feature class.  Like the &lt;code&gt;rename_fields&lt;/code&gt; function previously posted, it recreates the existing field mappings and modifies as necessary.  The output is a new feature class with fields in the order specified.&lt;/p&gt;

&lt;p&gt;The only caveat is that required fields always get pushed to the front (so the featureclass will start with OBJECTID, Shape, rest of fields&amp;hellip;).  After required fields are out of the way, the rest of the fields are added in the order specified in the &lt;code&gt;field_order&lt;/code&gt; list.  If any fields are missing, they are added to the end of the feature class.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import arcpy

def reorder_fields(table, out_table, field_order, add_missing=True):
    &amp;quot;&amp;quot;&amp;quot;
    Reorders fields in input featureclass/table
    :table:         input table (fc, table, layer, etc)
    :out_table:     output table (fc, table, layer, etc)
    :field_order:   order of fields (objectid, shape not necessary)
    :add_missing:   add missing fields to end if True (leave out if False)
    -&amp;gt; path to output table
    &amp;quot;&amp;quot;&amp;quot;
    existing_fields = arcpy.ListFields(table)
    existing_field_names = [field.name for field in existing_fields]

    existing_mapping = arcpy.FieldMappings()
    existing_mapping.addTable(table)

    new_mapping = arcpy.FieldMappings()

    def add_mapping(field_name):
        mapping_index = existing_mapping.findFieldMapIndex(field_name)

        # required fields (OBJECTID, etc) will not be in existing mappings
        # they are added automatically
        if mapping_index != -1:
            field_map = existing_mapping.fieldMappings[mapping_index]
            new_mapping.addFieldMap(field_map)

    # add user fields from field_order
    for field_name in field_order:
        if field_name not in existing_field_names:
            raise Exception(&amp;quot;Field: {0} not in {1}&amp;quot;.format(field_name, table))

        add_mapping(field_name)

    # add missing fields at end
    if add_missing:
        missing_fields = [f for f in existing_field_names if f not in field_order]
        for field_name in missing_fields:
            add_mapping(field_name)

    # use merge with single input just to use new field_mappings
    arcpy.Merge_management(table, out_table, new_mapping)
    return out_table
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;new_field_order = [&amp;quot;field2&amp;quot;, &amp;quot;field3&amp;quot;, &amp;quot;field1&amp;quot;]
reorder_fields(in_fc, out_fc, new_field_order)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;rsquo;ve tested this in 10.1.1+ - it may work in 10.0 as well and should work with any license level.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>