(<< Back <<) Typescript Examples (<< Back <<)
9. Drag-and-drop example
![](/TsLecture/MaxTs977_1.png)
![](/TsLecture/MaxTs989_1.png)
1 - Module Introduction.mp4 2 - Getting Started.mp4 3 - DOM Element Selection & OOP Rendering.mp4 4 - Interacting with DOM Elements.mp4 5 - Creating & Using an Autobind Decorator.mp4 6 - Fetching User Input.mp4 7 - Creating a Re-Usable Validation Functionality.mp4 8 - Rendering Project Lists.mp4 9 - Managing Application State with Singletons.mp4 10 - More Classes & Custom Types.mp4 11 - Filtering Projects with Enums.mp4 12 - Adding Inheritance & Generics.mp4 13 - Rendering Project Items with a Class.mp4 14 - Using a Getter.mp4 15 - Utilizing Interfaces to Implement Drag & Drop.mp4 16 - Drag Events & Reflecting the Current State in the UI.mp4 17 - Adding a Droppable Area.mp4 18 - Finishing Drag & Drop.mp4 19 - Wrap Up.mp4
Start from empty HTML and empty TS, for the moment al code will be stored to one file, splitting code to modules is next lecture
![](/TsLecture/MaxTs978_1.png)
![](/TsLecture/MaxTs979_1.png)
Replace Html ad CSS, we will use shadow DOM, Using templates and slots
![](/TsLecture/MaxTs980_1.png)
![](/TsLecture/MaxTs981_1.png)
![](/TsLecture/MaxTs982_1.png)
![](/TsLecture/MaxTs983_1.png)
Modern browser understand <template> html tag, browser don;t show it but tag can reach from JS https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template
![](/TsLecture/MaxTs984_1.png)
![](/TsLecture/MaxTs985_1.png)
![](/TsLecture/MaxTs986_1.png)
![](/TsLecture/MaxTs987_1.png)
So, we will use 3 templates on this project - project-input, single-project, project-list
![](/TsLecture/MaxTs988_1.png)
On the first Bash we do "NPM START" in another "TSC -W", browser will read port 3001 and TS compiler will track changing source code
![](/TsLecture/MaxTs999_1.png)
![](/TsLecture/MaxTs1000_1.png)
![](/TsLecture/MaxTs1001_1.png)
![](/TsLecture/MaxTs1002_1.png)
![](/TsLecture/MaxTs1003_1.png)
![](/TsLecture/MaxTs1004_1.png)
![](/TsLecture/MaxTs1005_1.png)
![](/TsLecture/MaxTs1006_1.png)
![](/TsLecture/MaxTs1007_1.png)
![](/TsLecture/MaxTs1008_1.png)
HtmlTemplate element globally available, because DOM library connected
![](/TsLecture/MaxTs1009_1.png)
![](/TsLecture/MaxTs1010_1.png)
![](/TsLecture/MaxTs1011_1.png)
![](/TsLecture/MaxTs1012_1.png)
![](/TsLecture/MaxTs1013_1.png)
Use explamation mark
![](/TsLecture/MaxTs1014_1.png)
Casting to HtmlTemplateElement
![](/TsLecture/MaxTs1015_1.png)
Alternative second syntax of casting is 'AS'
![](/TsLecture/MaxTs1016_1.png)
Idea is when we instantiated this class, immediately rendered <template> to <div>
![](/TsLecture/MaxTs1017_1.png)
![](/TsLecture/MaxTs1018_1.png)
So, now we have imported full document fragment structure
![](/TsLecture/MaxTs1019_1.png)
Atach will contains rendering logic
![](/TsLecture/MaxTs1020_1.png)
Document.InsertAdjacent method provided by Browser
![](/TsLecture/MaxTs1021_1.png)
![](/TsLecture/MaxTs1022_1.png)
![](/TsLecture/MaxTs1023_1.png)
But firstly we need to reach <form> element
![](/TsLecture/MaxTs1024_1.png)
![](/TsLecture/MaxTs1025_1.png)
And attach 7lt;form> element to <div> (host element)
![](/TsLecture/MaxTs1026_1.png)
![](/TsLecture/MaxTs1027_1.png)
Try how form will be attached from <template> and rendered
![](/TsLecture/MaxTs1028_1.png)
We have a style
![](/TsLecture/MaxTs1029_1.png)
before we attach element to DOM we will set element ID to bind it to style
![](/TsLecture/MaxTs1030_1.png)
Now site looks match better
![](/TsLecture/MaxTs1031_1.png)
![](/TsLecture/MaxTs1032_1.png)
![](/TsLecture/MaxTs1033_1.png)
Declare 3 new variable
![](/TsLecture/MaxTs1034_1.png)
![](/TsLecture/MaxTs1035_1.png)
![](/TsLecture/MaxTs1036_1.png)
![](/TsLecture/MaxTs1037_1.png)
And provide access to user input
![](/TsLecture/MaxTs1038_1.png)
Add EventHandler to form submit
![](/TsLecture/MaxTs1039_1.png)
![](/TsLecture/MaxTs1040_1.png)
parameter event:Event on Eventhandler
![](/TsLecture/MaxTs1041_1.png)
PreventDefault firstly, to prevent browser submission HttpRequest to server
![](/TsLecture/MaxTs1042_1.png)
This cause because This is different on AddEventListeners and class
![](/TsLecture/MaxTs1043_1.png)
![](/TsLecture/MaxTs1044_1.png)
![](/TsLecture/MaxTs1045_1.png)
Therefore we need to use bind(), we need pass this from addEventListener to submitHandler method of ProjectInput class, bind() is vanilla JS method.
![](/TsLecture/MaxTs1046_1.png)
![](/TsLecture/MaxTs1047_1.png)
And currently all working fine, we have access in submitHandler to user input
![](/TsLecture/MaxTs1048_1.png)
![](/TsLecture/MaxTs1049_1.png)
We will create AutoBind decorator to all project
![](/TsLecture/MaxTs1050_1.png)
![](/TsLecture/MaxTs1051_1.png)
Decorator interface for method
![](/TsLecture/MaxTs1052_1.png)
![](/TsLecture/MaxTs1053_1.png)
![](/TsLecture/MaxTs1054_1.png)
![](/TsLecture/MaxTs1055_1.png)
![](/TsLecture/MaxTs1056_1.png)
![](/TsLecture/MaxTs1057_1.png)
But firstly turn on decorator future on TS config
![](/TsLecture/MaxTs1058_1.png)
Or delete TS error "this parameter never used"
![](/TsLecture/MaxTs1059_1.png)
This two variable never used, musk it with underscore "_"
![](/TsLecture/MaxTs1060_1.png)
![](/TsLecture/MaxTs1061_1.png)
Now we replace implicit bind to decorator
![](/TsLecture/MaxTs1062_1.png)
![](/TsLecture/MaxTs1063_1.png)
gatherUserInput will processing input after submit
![](/TsLecture/MaxTs1064_1.png)
Function should return a Tuple with all 3 user input value
![](/TsLecture/MaxTs1065_1.png)
![](/TsLecture/MaxTs1066_1.png)
Trivial way is checking for non-empty value, but we need more smart and scalable solution
![](/TsLecture/MaxTs1067_1.png)
Convert string to number with ParseFloat or '+'
![](/TsLecture/MaxTs1068_1.png)
![](/TsLecture/MaxTs1069_1.png)
How to fix wrong input branch, we have no correct Tuple for return
![](/TsLecture/MaxTs1070_1.png)
return; get undefined as function result
![](/TsLecture/MaxTs1071_1.png)
![](/TsLecture/MaxTs1072_1.png)
![](/TsLecture/MaxTs1073_1.png)
Or we need to set Void instead undefined
![](/TsLecture/MaxTs1074_1.png)
![](/TsLecture/MaxTs1075_1.png)
Can we check function result as InstanceOf?
![](/TsLecture/MaxTs1076_1.png)
On runtime we have no way to check Tuple, because JS known nothing about Tuple, for JS level Tuple just simple Array
![](/TsLecture/MaxTs1077_1.png)
![](/TsLecture/MaxTs1078_1.png)
![](/TsLecture/MaxTs1079_1.png)
![](/TsLecture/MaxTs1080_1.png)
So, checking void or correct result of user input will be Array.IsArray
![](/TsLecture/MaxTs1081_1.png)
And check how function gatherUserInput return correct Tuple
![](/TsLecture/MaxTs1082_1.png)
![](/TsLecture/MaxTs1083_1.png)
Destructive assignment tuple to to 3 variables
![](/TsLecture/MaxTs1084_1.png)
Invalid input with '===' and '||' now will replace to call validator
![](/TsLecture/MaxTs1085_1.png)
![](/TsLecture/MaxTs1086_1.png)
or combine of 3 validate functions with '&&'
![](/TsLecture/MaxTs1087_1.png)
![](/TsLecture/MaxTs1088_1.png)
Interface of universal validator parameters
![](/TsLecture/MaxTs1089_1.png)
Define optional parameter by unity type with '| undefined' or by mark parameter name with question mark '?'
![](/TsLecture/MaxTs1090_1.png)
![](/TsLecture/MaxTs1091_1.png)
Pass object with interface Validatable to function Validate
![](/TsLecture/MaxTs1092_1.png)
Validation logic - we combine result with '&&'
![](/TsLecture/MaxTs1093_1.png)
Problem that don't sure what exactly we need to validate - string or number, in this case we need to use TypeGuard
![](/TsLecture/MaxTs1094_1.png)
![](/TsLecture/MaxTs1095_1.png)
![](/TsLecture/MaxTs1096_1.png)
![](/TsLecture/MaxTs1097_1.png)
Main developer mistakes - empty string (if length is zero) != null and != undefined
![](/TsLecture/MaxTs1098_1.png)
![](/TsLecture/MaxTs1099_1.png)
![](/TsLecture/MaxTs1100_1.png)
Testing validation - construct validation object and pass it as parameter to validation function, combine Validation with '&&' or with ! and '||'
![](/TsLecture/MaxTs1101_1.png)
![](/TsLecture/MaxTs1102_1.png)
![](/TsLecture/MaxTs1103_1.png)
For number Html5 allow set min and max numbers
![](/TsLecture/MaxTs1104_1.png)
Currently Submit handler doing nothing, only console.log
![](/TsLecture/MaxTs1105_1.png)
But we need to render ProjectList, Section element is common Html-element supported by Browser - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section
![](/TsLecture/MaxTs1106_1.png)
![](/TsLecture/MaxTs1107_1.png)
So, start class ProjectList, what will support rendering list
![](/TsLecture/MaxTs1108_1.png)
We can access to all needed HtmlElement
![](/TsLecture/MaxTs1109_1.png)
![](/TsLecture/MaxTs1110_1.png)
And add to constructor one parameter - with literal type active/finished and autoDeclaration
![](/TsLecture/MaxTs1111_1.png)
Dynamic element ID
![](/TsLecture/MaxTs1112_1.png)
Attach method will be rendered this list to the DOM
![](/TsLecture/MaxTs1113_1.png)
![](/TsLecture/MaxTs1114_1.png)
RenderContent will fill <h2> and <ul> tags
![](/TsLecture/MaxTs1115_1.png)
![](/TsLecture/MaxTs1116_1.png)
![](/TsLecture/MaxTs1117_1.png)
![](/TsLecture/MaxTs1118_1.png)
Instantiate project list
![](/TsLecture/MaxTs1119_1.png)
![](/TsLecture/MaxTs1120_1.png)
And checking how project list rendering from template to DOM
![](/TsLecture/MaxTs1121_1.png)
In this place we need to create new project section and attach project section to active Tab
![](/TsLecture/MaxTs1122_1.png)
![](/TsLecture/MaxTs1123_1.png)
Trivial idea is Get Active Tab and add new project to ActiveTab
![](/TsLecture/MaxTs1124_1.png)
But we create more powerful code, we create method AddProject
![](/TsLecture/MaxTs1125_1.png)
We need to pass reference for ProjectInput to constructor and call AddProject on the instance
![](/TsLecture/MaxTs1126_1.png)
![](/TsLecture/MaxTs1127_1.png)
This will be Global Project state, usually we used this way on Angular or Redux, at start point this is Array of Any, this is not final point.
![](/TsLecture/MaxTs1128_1.png)
AddProject is public method, because there are no qualificator
![](/TsLecture/MaxTs1129_1.png)
And push new project to teh ProjectState object
![](/TsLecture/MaxTs1130_1.png)
Create private constructor and static Instance variable, and GeInstance method, because ProjectStaite state is Singleton class
![](/TsLecture/MaxTs1131_1.png)
![](/TsLecture/MaxTs1132_1.png)
And call project state with NewProject
![](/TsLecture/MaxTs1133_1.png)
Create Listeners class, Project state need to collecting Listeners associated with each project
![](/TsLecture/MaxTs1134_1.png)
Listener should be a pointer to function
![](/TsLecture/MaxTs1135_1.png)
![](/TsLecture/MaxTs1136_1.png)
Idea is execute Listeners as function
![](/TsLecture/MaxTs1137_1.png)
Slice() create copy of Array
![](/TsLecture/MaxTs1138_1.png)
We want to pass listeners (if project state changed), this will be callback (func on VB)
![](/TsLecture/MaxTs1139_1.png)
![](/TsLecture/MaxTs1140_1.png)
![](/TsLecture/MaxTs1141_1.png)
![](/TsLecture/MaxTs1142_1.png)
![](/TsLecture/MaxTs1143_1.png)
Add new <li> to <ul>
![](/TsLecture/MaxTs1144_1.png)
Currently new project added to both list (new and finished)
![](/TsLecture/MaxTs1145_1.png)
![](/TsLecture/MaxTs1146_1.png)
![](/TsLecture/MaxTs1227_1.png)
Full code huge, part of lecture skipped
![](/TsLecture/MaxTs1228_1.png)
Visual update and change project status from Active to Finished
![](/TsLecture/MaxTs1229_1.png)
Start create two interface - Draggable and DragTarget
![](/TsLecture/MaxTs1230_1.png)
This interface will be add to any class what can be draggable - ProjectItem class
![](/TsLecture/MaxTs1231_1.png)
![](/TsLecture/MaxTs1232_1.png)
And the boxes class what save draggable element
![](/TsLecture/MaxTs1233_1.png)
Draggable interface need to implement two handlers - DragStartHandler and DragEndHandler
![](/TsLecture/MaxTs1234_1.png)
DragTarget interface need to implement 3 handler - DragOverHandler, DropHandler, DragLeaveHandler
![](/TsLecture/MaxTs1235_1.png)
![](/TsLecture/MaxTs1236_1.png)
![](/TsLecture/MaxTs1237_1.png)
![](/TsLecture/MaxTs1238_1.png)
![](/TsLecture/MaxTs1239_1.png)
![](/TsLecture/MaxTs1240_1.png)
![](/TsLecture/MaxTs1241_1.png)
Bind this handler with Decorator @AutoBind
![](/TsLecture/MaxTs1242_1.png)
![](/TsLecture/MaxTs1243_1.png)
Without draggable attribute on Html drag-and-drop don't working
![](/TsLecture/MaxTs1244_1.png)
And now item can draggable, we can see coordinates
![](/TsLecture/MaxTs1245_1.png)
![](/TsLecture/MaxTs1246_1.png)
Change style for more visible draggable element
![](/TsLecture/MaxTs1247_1.png)
![](/TsLecture/MaxTs1248_1.png)
![](/TsLecture/MaxTs1249_1.png)
![](/TsLecture/MaxTs1250_1.png)
![](/TsLecture/MaxTs1251_1.png)
Add style Droppable to <ul>
![](/TsLecture/MaxTs1252_1.png)
![](/TsLecture/MaxTs1253_1.png)
All JS Drag events
![](/TsLecture/MaxTs1254_1.png)
Implement other handlers
![](/TsLecture/MaxTs1255_1.png)
![](/TsLecture/MaxTs1256_1.png)
![](/TsLecture/MaxTs1257_1.png)
![](/TsLecture/MaxTs1258_1.png)
![](/TsLecture/MaxTs1259_1.png)
![](/TsLecture/MaxTs1260_1.png)
And remove style Droppable from <ul> when drag-and-drop finished
![](/TsLecture/MaxTs1261_1.png)
![](/TsLecture/MaxTs1262_1.png)
![](/TsLecture/MaxTs1263_1.png)
13. Google Map example + Axios HttpRequest library
![](/TsLecture/MaxTs885_1.png)
![](/TsLecture/MaxTs996_1.png)
Project setup, we want receive search string from user input and than pass string to Google Map and receive GeoCoordinates from Google and finally show Google Map
![](/TsLecture/MaxTs886_1.png)
![](/TsLecture/MaxTs887_1.png)
![](/TsLecture/MaxTs888_1.png)
![](/TsLecture/MaxTs889_1.png)
![](/TsLecture/MaxTs890_1.png)
![](/TsLecture/MaxTs891_1.png)
Make form submission firstly
![](/TsLecture/MaxTs892_1.png)
![](/TsLecture/MaxTs893_1.png)
![](/TsLecture/MaxTs894_1.png)
PreventDefault + Exclamation mark "!"
![](/TsLecture/MaxTs895_1.png)
![](/TsLecture/MaxTs896_1.png)
HtmlInputElement to access for Value
![](/TsLecture/MaxTs897_1.png)
![](/TsLecture/MaxTs898_1.png)
![](/TsLecture/MaxTs899_1.png)
![](/TsLecture/MaxTs900_1.png)
We will provide API key to URL request and receive coordinates from Google Maps
![](/TsLecture/MaxTs901_1.png)
![](/TsLecture/MaxTs902_1.png)
![](/TsLecture/MaxTs903_1.png)
![](/TsLecture/MaxTs904_1.png)
![](/TsLecture/MaxTs905_1.png)
Setup Google API and receive Google Map key. Google map meed credit card.
![](/TsLecture/MaxTs906_1.png)
![](/TsLecture/MaxTs907_1.png)
![](/TsLecture/MaxTs908_1.png)
![](/TsLecture/MaxTs909_1.png)
![](/TsLecture/MaxTs910_1.png)
![](/TsLecture/MaxTs911_1.png)
![](/TsLecture/MaxTs912_1.png)
![](/TsLecture/MaxTs913_1.png)
![](/TsLecture/MaxTs914_1.png)
![](/TsLecture/MaxTs915_1.png)
![](/TsLecture/MaxTs916_1.png)
Pass key to project
![](/TsLecture/MaxTs917_1.png)
![](/TsLecture/MaxTs918_1.png)
We can simple use JS Fetch API
![](/TsLecture/MaxTs919_1.png)
But we use Axios library. Install it.
![](/TsLecture/MaxTs920_1.png)
![](/TsLecture/MaxTs921_1.png)
![](/TsLecture/MaxTs922_1.png)
Axios already has index.d.ts a and don't need install @types
![](/TsLecture/MaxTs923_1.png)
![](/TsLecture/MaxTs924_1.png)
![](/TsLecture/MaxTs925_1.png)
We can see all request and response types and in index.d.ts
![](/TsLecture/MaxTs926_1.png)
Pass URL from Google to project and add API key
![](/TsLecture/MaxTs927_1.png)
![](/TsLecture/MaxTs928_1.png)
![](/TsLecture/MaxTs929_1.png)
We must use EncodeUrl because API key can contains special characters
![](/TsLecture/MaxTs930_1.png)
![](/TsLecture/MaxTs931_1.png)
Axois Get return Promise, therefore we need to use then and catch
![](/TsLecture/MaxTs932_1.png)
![](/TsLecture/MaxTs934_1.png)
![](/TsLecture/MaxTs935_1.png)
Request to Google ready, time to try
![](/TsLecture/MaxTs936_1.png)
![](/TsLecture/MaxTs937_1.png)
![](/TsLecture/MaxTs938_1.png)
We can see array of result points, usually first is best
![](/TsLecture/MaxTs939_1.png)
We need extract Latitude and Longitude from first array item
![](/TsLecture/MaxTs940_1.png)
![](/TsLecture/MaxTs941_1.png)
![](/TsLecture/MaxTs942_1.png)
For Promise this is simple, this is not Observable, but Axois is generic library and we need to define structure of Google response
![](/TsLecture/MaxTs943_1.png)
![](/TsLecture/MaxTs944_1.png)
Define type GoogleGeoCodingResponse and make result Axois.Get result typed
![](/TsLecture/MaxTs945_1.png)
![](/TsLecture/MaxTs946_1.png)
Look to All status what Google can return
![](/TsLecture/MaxTs947_1.png)
![](/TsLecture/MaxTs948_1.png)
Define status as union type with Literal type and add that status to GoogleGeoCodingResponse. We have 7 types of response, but no one interesting for us, except OK
![](/TsLecture/MaxTs949_1.png)
Throw new Error if status different than 'OK'
![](/TsLecture/MaxTs950_1.png)
![](/TsLecture/MaxTs951_1.png)
Grab script what can show Map and Delete InitMap callback
![](/TsLecture/MaxTs952_1.png)
![](/TsLecture/MaxTs953_1.png)
![](/TsLecture/MaxTs954_1.png)
![](/TsLecture/MaxTs955_1.png)
![](/TsLecture/MaxTs956_1.png)
And call Show Google Map on Than branch
![](/TsLecture/MaxTs957_1.png)
Google not defined on TS code, therefore we need Declare var Google:any;
![](/TsLecture/MaxTs958_1.png)
Look to Google how to render Marker and set marker with needed coordinates
![](/TsLecture/MaxTs959_1.png)
![](/TsLecture/MaxTs960_1.png)
![](/TsLecture/MaxTs961_1.png)
![](/TsLecture/MaxTs962_1.png)
Check how project working
![](/TsLecture/MaxTs963_1.png)
![](/TsLecture/MaxTs964_1.png)
![](/TsLecture/MaxTs965_1.png)
Check how error captured on catch branch, change Maps to Map.
![](/TsLecture/MaxTs966_1.png)
![](/TsLecture/MaxTs967_1.png)
![](/TsLecture/MaxTs968_1.png)
![](/TsLecture/MaxTs969_1.png)
To use all Google API correctly we can install @types/GoogleMap
![](/TsLecture/MaxTs970_1.png)
![](/TsLecture/MaxTs971_1.png)
![](/TsLecture/MaxTs972_1.png)
![](/TsLecture/MaxTs973_1.png)
And now we can see errors of call Google API on compilation time
![](/TsLecture/MaxTs974_1.png)
![](/TsLecture/MaxTs975_1.png)
Best practice is fixing used library on config (--save-dev on installation)
![](/TsLecture/MaxTs976_1.png)
There are open alternatives to Google - without Credit card and money
![](/TsLecture/MaxTs933_1.png)
Related pages
- Angular documentation
- Typescript documentation
- Javascript documentation
- ECMAScript ES6 vs Typescript
- React vs Angular
- (2024) Google Cloud and Cloudflare
- (2023) CloudflareWorker and Supabase
- (2022) JS, Css
- (2022) Typescript, Webpack
- (2022) Angular, RxJs, Firebase, MongoDb
- (2022) Node, NestJs, Electron, Pwa, Telegram
- (2022) React, Redux, GraphQL, NextJs
- (2022) Angular/Typescript, JS books
![](http://forum.vb-net.com/GetTopicCount.png?id=52475b70-2796-4553-a442-ba3a4d12f055)
<SITEMAP> <MVC> <ASP> <NET> <DATA> <KIOSK> <FLEX> <SQL> <NOTES> <LINUX> <MONO> <FREEWARE> <DOCS> <ENG> <CHAT ME> <ABOUT ME> < THANKS ME> |