[//]: # (TOC generated with https://github.com/jonschlinkert/markdown-toc)
- [4.x Widget Development Guide [INTERNAL]](#4x-widget-development-guide-internal)
* [Widget development requirements](#widget-development-requirements)
+ [Node](#node)
+ [TypeScript](#typescript)
+ [JSX](#jsx)
+ [`esri/core/Accessor`](#esricoreaccessor)
+ [Sass](#sass)
* [Widget development setup](#widget-development-setup)
* [`esri/widgets/Widget`](#esriwidgetswidget)
* [Building `HelloWorld` widget](#building-helloworld-widget)
+ [Simple `HelloWorld`](#simple-helloworld)
+ [Defining properties](#defining-properties)
+ [Defining methods](#defining-methods)
+ [Responding to DOM events](#responding-to-dom-events)
+ [Responding to synthetic events](#responding-to-synthetic-events)
+ [Styling `HelloWorld` widget](#styling-helloworld-widget)
+ [Internationalizing `HelloWorld` widget](#internationalizing-helloworld-widget)
+ [Making `HelloWorld` accessible](#making-helloworld-accessible)
+ [Dynamic UI](#dynamic-ui)
+ [Putting it all together](#putting-it-all-together)
+ [Using `HelloWorld` widget](#using-helloworld-widget)
* [Advanced concepts](#advanced-concepts)
+ [Working with a viewModel](#working-with-a-viewmodel)
+ [`render()`](#render)
+ [Render relevant elements only](#render-relevant-elements-only)
+ [Binding](#binding)
+ [Distinguishable children](#distinguishable-children)
+ [Composite widgets](#composite-widgets)
+ [Dynamic CSS classes](#dynamic-css-classes)
+ [Dynamic inline styles](#dynamic-inline-styles)
+ [Spreading properties/attributes](#spreading-propertiesattributes)
* [TypeScript widget decorators](#typescript-widget-decorators)
+ [Properties](#properties)
+ [Methods](#methods)
* [Gotchas](#gotchas)
* [Widget file structure](#widget-file-structure)
* [Styling](#styling)
+ [Sass](#sass-1)
+ [CSS](#css)
* [ViewModel](#viewmodel)
* [Best Practices](#best-practices)
* [Tips](#tips)
+ [Behind the scenes](#behind-the-scenes)
* [Q&A](#qa)
* [Additional Examples](#additional-examples)
+ [Widgets](#widgets)
+ [Patterns](#patterns)
* [Additional References](#additional-references)
* [Unresolved/Workarounds](#unresolvedworkarounds)
* [Known issues (working on it!)](#known-issues-working-on-it)
* [Breaking changes](#breaking-changes)
* [Notes](#notes)
# 4.x Widget Development Guide [INTERNAL]
Widgets are reusable user-interface components and are key to providing a rich user experience. The ArcGIS for JavaScript API provides a set of ready-to-use widgets and also provides a foundation for you to create custom widgets.
This document will walk through developing a custom widget and also how to use a widget in an ArcGIS for JavaScript API application.
## Widget development requirements
### [Node](https://nodejs.org/en/)
Node is a JavaScript runtime environment and it powers some of the tooling used for widget development. It'll mostly be used to install all development dependencies and to compile our TypeScript and Sass.
### [TypeScript](https://www.typescriptlang.org/)
> TypeScript
> JavaScript that scales.
> TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
> Any browser. Any host. Any OS. Open source.
Widget development is done in TypeScript and the following are some of its main features:
* statically-typed
* transpiles ES6 to ES5 (our current target)
* class-based
The [TypeScript Tutorial](https://www.typescriptlang.org/docs/tutorial.html) and [Sitepen's Definitive Guide to TypeScript](https://www.sitepen.com/blog/2013/12/31/definitive-guide-to-typescript/) are excellent resources to start learning TypeScript.
Although not required, a code editor that supports TypeScript will ease development. See [TypeScript Editor support](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support) for more details.
### [JSX](https://facebook.github.io/jsx/)
JSX is a JavaScript extension syntax that allows us to describe our widget UIs similarly to HTML.
See [JSX in depth](https://facebook.github.io/react/docs/jsx-in-depth.html) for more information.
**Note:** Not all concepts from React resources are applicable.
### `esri/core/Accessor`
Accessor is one of the core features of 4.0 and it is the base for all classes. It is the foundation for widgets, so knowledge of Accessor will come pretty handy. It is strongly recommended to read learn [`Accessor` TypeScript usage patterns](https://devtopia.esri.com/WebGIS/arcgis-js-api/wiki/%5B4.0-Guides%5D-Accessor-usage-patterns-in-typescript) to become familiar with best practices using Accessor + TypeScript.
### [Sass](http://sass-lang.com/)
Sass is a CSS preprocessor that allows us to use variables, mixins, and functions. Widget CSS is authored in Sass in an effort to make it easier to style and to ensure a consistent look across widgets.
## Widget development setup
**Note:** The following steps assume the developer is working with the `arcgis-js-api` 4.x repo and that submodules have been initialized.
* Run `npm install && npm run start`
* Each widget belongs in a `.tsx` file, which allows us to use JSX to define our UIs.
* Each widget should have a reference to it in [`tsconfig.json`](https://devtopia.esri.com/WebGIS/arcgis-js-api/blob/4master/tsconfig.json#L13). Place entries in alphabetical order.
**Note:** this step will no longer be needed when [TypeScript 2.0](https://github.com/Microsoft/TypeScript/wiki/Roadmap#20) rolls out (see *Glob support in tsconfig.json*).
## `esri/widgets/Widget`
This module is the base for all ArcGIS for JavaScript API widgets. Like most 4.0 modules, it extends [`Accessor`](https://developers.arcgis.com/javascript/latest/api-reference/esri-core-Accessor.html). We are also able to leverage JSX to define our UIs.
The core principle for widgets is that the UI is created and updated inside `render()`. This method will rely on widget properties and methods (typically from the viewModel) for rendering.
It is recommended to design your widget to minimize relying on state to reduce complexity. Although this is not always possible, strive for simplicity when building your widget.
**Lifecycle**
* `constructor(params)` – †
* `postInitialize()` – this method is called when the widget's properties are ready, but before rendering
* `startup()` – deprecated; added for backwards-compatibility only
* `destroy()` – this method should be used to free up widget resources to ensure proper garbage collection
**Methods**
* `render()` – method where the UI is rendered
* `scheduleRender()` – invalidates the UI and schedules a subsequent render
* `on(eventType, listener)` – method used to register event listeners
* `emit(event, eventObject)` – method used to emit events
**Properties**
* `viewModel` – the widget's viewModel
† `srcNodeRef` is only needed when consumed outside of a Widget [see Composite widgets](#composite-widgets)
**Note**: This is not a 1:1 replacement for React/Dijit, etc...
As a developer, you will typically implement `postInitialize`, `destroy` and `render`; as well as define custom widget methods/properties.
Also, unlike `dijit/_WidgetBase`, `esri/widgets/Widget` will automatically call `destroy` on all superclasses when destroyed.
## Building `HelloWorld` widget
The following shows how to build `HelloWorld` widget.
**Note** This section assumes knowledge of [`Accessor` TypeScript usage patterns](https://devtopia.esri.com/WebGIS/arcgis-js-api/wiki/%5B4.0-Guides%5D-Accessor-usage-patterns-in-typescript)
```js
var helloWorld = new HelloWorld({}, "helloWorldDiv");
// renders <div>Hello, my name is Art Vandelay!</div>
```
### Simple `HelloWorld`
**HelloWorld.tsx**
```tsx
/// <amd-dependency