Building Your Own Widget with the ArcGISBuilding Your Own Widget with the ArcGISAPI for JavaScriptAPI for JavaScript
Matt Driscoll – Matt Driscoll –
JC Franco – JC Franco –
@driskull@driskull
@arfncode@arfncode
AgendaAgendaAbout WidgetsWidget FrameworkStylingBuild A Widget!
WidgetsWidgets
AboutAboutWhat?
Encapsulated UI componentsCohesive (integrated, uni�ed)Single-purpose pieces of functionality
Why?ReusableInterchangeable
How?esri/Widgets/Widget
Widget FrameworkWidget Framework
ArchitectureArchitectureViews + ViewModels
Separation of concernsReusable
UI replacementEasier integration
Built with TypeScript
ViewsViewsExtend esri/widgets/WidgetRely on ViewModelFocus on UI
ViewModelsViewModelsExtend esri/core/AccessorProvide APIs to support viewFocus on business logic
View + ViewModel in actionView + ViewModel in actionView renders its state
state = view + ViewModel propsView calls VMs APIs
causes a change (e.g., property or result)View updates
esri/widgets/Widgetesri/widgets/WidgetLifecycleAPI consistency
Uni�ed object constructorPropertiesWatching
LifecycleLifecycleconstructorpostInitializerenderdestroy
renderrenderDe�nes UIReacts to stateUses JSXVDOM
renderrender example examplerender() { const { x, y, scale } = this; return ( <div bind={this} class={CSS.base} onclick={this._handleClick} title="map info" tabIndex={0}> <p>x: {x}</p> <p>y: {y}</p> <p>scale: {scale}</p> </div> ); }
Widget rendering
ImplementingImplementingDecoratorsDecorators
@subclass + declared@property
autocastcomputedread-onlyaliased
@aliasOf@renderable@accessibleHandler
ImplementingImplementingExtend esri/widgets/Widget
/// <amd-dependency path="esri/core/tsSupport/declareExtendsHelper" name="__extends" /> /// <amd-dependency path="esri/core/tsSupport/decorateHelper" name="__decorate" /> @subclass("MyWidget") class MyWidget extends declared(Widget) { } export = MyWidget;
ImplementingImplementingImplement render
// ... class MyWidget extends declared(Widget) { render() { return ( <div>I'm a widget</div> ); } } // ...
ImplementingImplementingDe�ne properties
// ... @property() @renderable() name: string = "I'm a widget"; render() { return ( <div>{this.name}</div> ); } // ...
New in 4.7New in 4.7Uni�ed CSS classesAnimation hooksDefault iconClass and label properties
Uni�ed CSS classesUni�ed CSS classesUse class attributeWidget#classes builds node classjoin utility is deprecatedclasses attribute is deprecated
Uni�ed CSS classesUni�ed CSS classes// 4.6 render() { const dynamicClasses = { [CSS.active]: this.isActive }; return ( <div class={join(CSS.base, CSS.mixin)} classes={dynamicClasses}>{/* ... */}</div> ); }
Uni�ed CSS classesUni�ed CSS classes// 4.7 render() { const dynamicClasses = { [CSS.active]: this.isActive }; return ( <div class={this.classes(CSS.base, CSS.mixin, dynamicClasses)}>{/* ... */}</div> ); }
Animation hooksAnimation hooksCSS or JSNode attributesenterAnimationexitAnimationupdateAnimation (JS-only)
cssTransition (CSS-only)
Animation hooksAnimation hooksrender() { const { visible } = this; const content = visible ? ( <div enterAnimation={cssTransition("enter", CSS.fadeIn)} exitAnimation={cssTransition("exit", CSS.fadeOut)}>{/*...*/}</div> ) : null; return ( <div class={CSS.base}> {content} </div> ); }
iconClassiconClass and and labellabelUI hints for container widgetsExpand uses iconClass ( )
iconClass - class namelabel – localized widget label
exampleEsri icon font
@subclass("MyWidget") class MyWidget extends declared(Widget) { @property() iconClass: string = "esri-icon-basemap"; @property() label: string = i18n.widgetLabel; }
RecapRecapViews + ViewModelsesri/widgets/Widgetrender()
StylingStyling
How?How?BEMSass
Naming CSS classesNaming CSS classesBlock Element Modi�er (Block Element Modi�er ( ) )
Scopes styles to blocksSemanticLow speci�city
BEMBEM
// block .example-widget {} // block__element .example-widget__input {} // block--modifier .example-widget--loading {} // block__element--modifier .example-widget__input--disabled {}
Styling with Styling with CSS preprocessorPowered-up CSS
NestingVariablesFunctionsMixinsInheritance
SassSass
Sass makes it easier to...Sass makes it easier to...RestyleOrganizeWrite less code :)
RecapRecapBEMSass
Let's build a widget!Let's build a widget!Bookmarks DocBookmarks Completed Demo
VM: API DesignVM: API Designinterface BookmarksViewModel { bookmarkItems: Collection<BookmarkItem>; state: "loading" | "ready" | "disabled"; // will be computed property view: MapView; goTo(item: BookmarkItem): IPromise<any>; } interface BookmarkItem { active: Boolean; extent: Extent; name: string; }
Build StepsBuild StepsDemo StartHTML StepsViewModel StepsView StepsSass Steps
Let's RecapLet's RecapWidgets are single functionality UI componentsWe use them for reusability/interchangeabilityWidget FrameworkConstructing a widget
ViewModelsViews
StylingBEMSass
Suggested SessionSuggested SessionArcGIS API for JavaScript: Customizing Widgets
Additional ResourcesAdditional ResourcesImplementing AccessorSetting up TypeScriptWidget DevelopmentJS API SDKStylingWidget Patterns
Questions?Questions?For exampleFor example
� �
� Where can I �nd the slides/source?
esriurl.com/buildwidgetsds2018
Thank you!Thank you!