Quantcast
Channel: Jeffry Houser's Blog
Viewing all 497 articles
Browse latest View live

Creating a Production Build - Building Angular 2 Applications with Gulp - Part 9

$
0
0
This is part of an ongoing series about building Angular 2 TypeScript applications with Gulp. Start with Part 1, and then read Part 2, Part 3, Part 4, Part 6, Part 7, and Part 8. Sometimes I like to create a build intended for production servers which does not include source maps. To make that happen, I use a gulp-if plugin to conditionally decide whether to generate the source maps, or not. First, install gulp-if: npm install --save-dev gulp-if You'll see an install screen like this: Now, import the gulp-if library as part of the gulpfile.js: var gulpIf = require('gulp-if'); Before we modify the buildTS task, let's add a variable named devMode: var devMode = true; This is the variable we will use to determine whether or not to generate the source maps. It is set to true by default. Primarily we will change this variable as part of tasks, not as a configuration option. Review the buildTS task: gulp.task("buildTS", ["tslint"], function() { return gulp.src(typeScriptSource) .pipe(sourcemaps.init()) .pipe(tsProject()) .pipe(uglify()) .pipe(sourcemaps.write(mapPath)) .pipe(gulp.dest(destinationPath)); }); We want to use gulp-if as part of the two source map statements. First replace the source map init statement: .pipe(gulpIf(devMode,sourcemaps.init())) Instead of just calling sourcemaps.init(), we now wrap it in a gulpIf. This will check the devMode variable and conditionally init the source maps. Also change the sourcemaps.write() pipe: .pipe(gulpIf(devMode,sourcemaps.write(mapPath))) With the buildTS task updated, we can now create a task for building a production version of the app. The purpose of this task is to set the devMode value to false; and then run the cleanBuild task: gulp.task('buildProd', function(){ devMode = false; gulp.start('cleanBuild') }); We can use gulp.start() to run the cleanBuild task. Running cleanBuild will delete the build directory, and then run the build task to compile the TypeScript files, move the HTML, and move the JavaScript libraries. Run the task: gulp buildProd You should see this: Take a look at the build directory: You'll notice that the maps directory is missing; meaning that the sourcemaps were successfully bypassed when running the cleanBuild. We can use this same approach to perform other actions as part of a build process. In the future, I plan to make changes to the buildProd script to force the Angular application into production mode, instead of development mode by default.

What's Next?

I have one final entry prepared for this blog series. The next one will talk about recompiling code as you make changes. Get our white paper for even more information:
Get our expanded 38-page version: Building Angular 2 Applications with Gulp.

Watch For Code Changes - Building Angular 2 Applications with Gulp - Part 10

$
0
0
This is part of an ongoing series about building Angular 2 TypeScript applications with Gulp. Start with Part 1, and then read Part 2, Part 3, Part 4, Part 6, Part 7, Part 8, and Part 9. There was one more thing I wanted to touch on for the purposes of this article. When changing code, I want the app to automatically be recompiled. Gulp provides built in functionality to make that happen. Iterative builds help improve performance, and get you reviewing your app in the browser without having to manually compile every time.

Watch for TypeScript changes

Create a task named buildWatch: gulp.task('buildWatch', ['build'], function(){ } The first thing this task does is build the application. The array before the function does this. This makes sure that we have the most recent code in the build directory before we start making changes. Then we need to start watching for changes. We can use the watch() method of gulp to do this. First, the TypeScript files: gulp.watch(typeScriptSource,['buildTS']) .on('change', function(event){ console.log('File Path' + event.path); }) The first argument to the watch() function is the glob array that points to the TypeScript source. The second argument is an array which represents the tasks to execute when a change is detected. In this case, the buildTS task is executed. When a change is detected, I chained an on() event after the watch() task. This outputs the name of the file that changed. Let's try this: gulp buildWatch You should see something like this: Notice that you are not sent back to the console prompt after running this. The task is waiting for something to happen. Change the main.ts file by adding something simple like this to the end: console.log('something'); Then look at the console: The changed file was output the console, and the buildTS was re-run. The buildTS task runs tslint before building the code; that has not changed.

Watch for HTML and JavaScript Changes

You can use the exact same approach for watching changes with HTML and the JS Libraries. Add these to the buildWatch task: gulp.watch(htmlSource,['copyHTML']).on('change', function(event){ console.log('File Path' + event.path); }) gulp.watch(javaScriptLibraries,['copyJSLibraries']).on('change', function(event){ console.log('File Path' + event.path); }) As files are changed, the relevant tasks are rerun. I don't usually watch the Angular libraries because they are rarely changed or updated during development unless it is a big project decision.

Final Thoughts

Build scripts are important. When I started doing Angular 1 development with JavaScript, I could just use JavaScript directly in the browser and was able to push off dealing with build scripts to a future time. However, when using Angular 2 with TypeScript, the build process became much more important since a compile process is needed before you can test your code. I had to jump in earlier than I would have otherwise. Remember, you can get all the code for this series in our seed project repository. Thank you for reading, be sure to sign up on our mailing list to get information like this direct to your inbox each month.
Get our expanded 38-page version: Building Angular 2 Applications with Gulp.

How do I do a search and replace in SQL?

$
0
0
I recently upgraded this blog to run exclusively on SSL. The first thing I noticed is that many of the links and image references inside blog posts were not HTTPS and the browser would show one of those 'this page is not secure errors'. The reason that the text of my posts use absolute links instead of relative is so that they'll show up properly for those who consume the blog via RSS and read it elsewhere. I spent a few hours white boarding a bubble sort algorithm before deciding I was getting nowhere, I decided to try a Google Search for the answer. In SQL Server, which is my blog's data store, you can use a replace function to make the change. I can do a simple search for text inside a column and replace it with something else. Perfect, that is what I need. Here is a StackOverflow answer with more details. The query they recommend is: update my_table set column = replace(column,'oldstring', 'newstring') Of course, when I did that I immediate got a conversion error. The body of these posts are stored as ntext fields inside the database. and the replace() function will not work on ntext or text fields. Thankfully, there is a solution to that too. A simple cast addressed the issue. update my_table set column = cast(replace(cast(column as nvarchar(max)),'oldstring', 'newstring') as ntext) If you use BlogCFC and need to do this on one of your blogs, here is the final script I used: update tblBlogEntries set body = cast(replace(cast(body as nvarchar(max)), 'http://www.jeffryhouser.com', 'https://www.jeffryhouser.com') as ntext) where body like '%http://www.jeffryhouser.com%' update tblBlogEntries set morebody = cast (replace(cast(morebody as nvarchar(max)), 'http://www.jeffryhouser.com', 'https://www.jeffryhouser.com') as ntext) where morebody like '%http://www.jeffryhouser.com%' I hope this helps someone.
Sign up for DotComIt's Monthly Technical Newsletter

How do I move ColdFusion Configuration to Another machine without Exporting Settings?

$
0
0
I've written in the past about migrating ColdFusion instances from one machine to another. Most of the time when I have to do this it is because of a hardware failure and I'm setting up a machine from scratch. This seems to happen every 4-6 years. Despite it's impending immediate death, 20 years running, I still do a quite bit of ColdFusion development. It's the devil that I know on the server side. Without a working machine, I can't sign into the CF Administrator and export CF Admin settings, so I have to go to other methods to get my config up and running. I've written about similar experiences with ColdFusion 8 and migrating from ColdFusion 8 to 9. But, time moves on and most of my production clients use CF10, so that is the version I have installed on my local. How do I get the old CF configuration set up the new machine when all I have access to is the old CF installation directory? this is how I did it.
  1. Install Apache: ColdFusion is useless without a web server, so first I installed and configured the Apache web server.
  2. Install ColdFusion 10: Get ColdFusion 10 from the cfmlRepo site. More specifically, go here. be sure to download app the patches. And send thanks to whomever takes care of that site.
  3. Install CF Hotfixes: Next, install all the ColdFusion hotfixes. You'll have to install the first few manually before you can use the update feature inside the ColdFusion administrator. Uses these instructions, but basically do this: C:\ColdFusion10\jre\bin\java -jar hotfix_008.jar I installed hotfixes 7-13. The rest I updated through the ColdFusion administrator.
  4. Compare Directories: Now compare your old ColdFusion install directory to the new ColdFusion install directory. You'll be surprised at how many of the files will be flagged as identical. Those aren't the ones you need to worry about. I focused on the config files in cfusion\lib\*.xml, and copied them over from the old directory to the new one. These are the configurations I moved:
    • new-cron.xml: Not sure what this one is for.
    • neo-datasource.xml: this file contains DSN configuration information.
    • neo-debug.xml: This contains CF Debugging settings.
    • neo-logging: This contains log related settings.
    • neo-mail.xml: This contains mail server settings.
    • neo-metric.xml: I couldn't figure out which settings this one contains, but I copied it anyway.
    • neo-runtime.xml: This file contains misc settings.
    I was making some educated guesses here. I think Neo was the code name for ColdFusion MX, so it is funny to see the name still kicking around.
  5. Restart ColdFusion: After the restart, you should find all your CF settings restored.
  6. Change DNS Passwords: I did notice that I had to reenter the passwords for all my data sources.
Overall, the process worked a lot better than I would have hoped.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

Why does reloading my Angular 2 App return a 404 error?

$
0
0
I've been having some issues with Angular 2 [now Angular 4] and the RouterModule. I put together this screencast to demonstrate the problem and how I fixed it:

How do I fix "Filename too long' error on SmartGit on Windows?

$
0
0
I've been working with a client on a project that uses AEM and ran into a problem committing code changes to their git repository. The error told me that the filename was too long. The error was something like this: error: unable to create file 'really long path to file' Filename too long I banged my head on this for a bit, but eventually found a solution. I had to change a flag with the version of Git that was included with SmartGit. Open up a console window. Move to your SmartGit install directory. For me that was: C:\Program Files (x86)\SmartGit\ You should have a git subdirectory in there. Switch to it, and drill down into the bin directory. My full path would be this: C:\Program Files (x86)\SmartGit\git\bin Now run this command: git config --system core.longpaths true And try the commit again. Things should work fine.

How do I right align a div inside a div?

$
0
0
I was working with a client to create a specific layout on the page and I wanted to align a div inside another div. But, I couldn't use text-align because I didn't want to right align the text elements in the inner div. How do you do it? First, create the outer div and inner div:
This is Text in the inner div
Some other Text
A simple div is inside another div, and the inner div has some text. The outer div's only purpose is a wrapper for positioning purposes. Both the outerDiv and innerDiv have CSS Styles attached. This is the CSS for the outerDiv: .outerDiv { display: flex; float : right; } It enables the outerDiv to use flexbox styling and floats the content to the right. Flexbox is an advanced way to position CSS elements. The innerDiv doesn't need any special CSS styling to make this work, but let's give it a background color: .innerDiv{ background: #e6e6e6; }Play with the code here. The implementation is really simple once you figure it out; but sometimes getting there is a stumble.

How can I control the parameter order when doing a HTTP POST call from Flex?

$
0
0
I've been working on a legacy AIR application for a client. It integrates with a backend I have no control over. According to their documentation, we need to pass the form parameters in a specific order. This seems unusual for a form post, which contains key-value pairs and is probably not accessed in parameter order. But due to other problems integrating with this service, I decided to see what I could do to specify the parameter order and remove that as a possible point of failure. I wrote about my attempts in this StackOverflow question.

What Didn't Work

This is what we were doing. First, create an HTTPService: Then, create the parameter object in code: var parameters : Object = new Object(); parameters.firstParameter = "firstOne"; parameters.amount = 100; parameters.otherParameters = "Other Random Misc Data"; parameters.lastParameter = "LastOne"; When the parameter object is created for the service call, I added the parameters to the object in order. Then make the call: var call : Object = this.service.send(parameters); call.addResponder( this.responder ); You may have already guessed why this won't work. Object parameters, or keys in a dictionary, are by definition, not in any specific sort order. When the Flex code looped over all parameters to add them to the outgoing service, it was accessing them in alphabetical order. However, that is not something I would bet my life on happening every single time due to the unordered nature of object properties. I also noticed that the outgoing request in the Flash Builder network monitor had the parameters in yet another order. Something with them changed between the Flex code and the server hit. So, what am I to do?

Using Lower Level APIs to make this work

The final solution was to use lower level APIs. I created the request using URLRequest and URLLoader classes. Instead of passing an object to the request I also had to manually create the request body which is very similar to a URL parameter string. First, create the parameter string: var parameters : String = ''; parameters += "firstParameter=firstOne&"; parameters += "amount=100&"; parameters += "otherParameters=Other Random Misc Data&"; parameters+= "lastParameter=LastOne"; Then, create the URLRequest: var r:URLRequest = new URLRequest(yourURLHere); r.data = parameters; r.method = URLRequestMethod.POST; r.contentType = "application/x-www-form-urlencoded"; The data is set to the parameters string. The method is set to POST and the contentType is set to 'application/x-ww-form-urlencoded'. And finally, create the URLLoader: var l:URLLoader = new URLLoader(); l.addEventListener(Event.COMPLETE, myResultMethod); l.addEventListener(IOErrorEvent.IO_ERROR, myFailureMethod ); l.addEventListener(SecurityErrorEvent.SECURITY_ERROR, myFailureMethod ); l.load(r); After doing this I could see in the outgoing requests that the parameter order was retained. So, things were good and my issue was solved! This is a lot more tedious than using the HTTPService, but at least I eliminated it as a possible error.

How can I revert a Git directory without affecting all changes?

$
0
0
I have been working on a specific code change with a client for about two weeks. This included about a dozen commits to the git repository before making a pull request. The client reviewed the pull request before merging, and requested I roll back a few changes. I had made these commit 8 commits ago, and from the dozens of files changed I only had to roll back two. How do you do it? I didn't see an obvious way to roll back just those files using SmartGit, my tool of choice, so I had to drop back to the command line. This did it: git checkout SHA-Value /c/path/to/repo/root/path/to/subdirectory/with/rejected/changes The SHA is the unique identifier for each commit. I opened up SmartGit, viewed a change log, found out which commit I changed these files, went to the commit before that, clicked 'details' and the SHA value is listed right there. You can also get the SHA value from GitHub if you prefer. Go into the Pull Request, and select commits. The value is in the table, to the right of the commit message. The path to the directory is your local system path. I had to use the absolute path. Since I'm a Windows user that started with the C drive, drilled down into my project folder, to the repository. And then I drilled down deeper into the repository to find the specific subdirectory I wanted to revert. Reverting the subdirectory is easier than reverting all the files individually. I executed the line inside of GitShell. Everything worked. I found a bunch of posts covering this topic, but most of them confused me. Hopefully this helps someone. Let me know!

Goodbye Flash

$
0
0
Adobe announced an End of Life for the Flash Player. I've written things in defense of Flash in the past and thought it would be worth it to revisit those statements today.

Who Am I?

If you came across this without knowing me, I am arguably one of the best Flex Developers in the world. I tied my business and professional life to the Flash Platform, and Flex, more than a decade ago. Here are some of my credentials:
  • I produced two Flex podcasts. a href="http://www.theflexshow.com">The Flex Show presented highly edited community interviews. and The Flextras Friday Lunch was a live demo with Q&A.
  • I created Flextras, a business selling Flex components.
  • I was editor in chief of the short-lived Flex Authority magazine.
  • I spoke at dozens of Flash based user groups and conferences.
  • I answered a ton of questions on StackOverflow and still retain the top spot in the Flex user charts.
  • I became an Adobe Community Professional due to my work in the Flash community.
  • I was one of the founding PMC members of the Apache Flex team.
Back then, I bet that Flex would provide a better application building experience than anything HTML could offer. I thought it would rule the world. I wanted to get in early and ride the wave to success. I took a calculated risk that turned out to be wrong.

Why Does Adobe's Decision Makes Sense?

Browsers have slowly been shutting down their plugin APIs and Flash Player was a plugin. Flash was able to get around this because it is widely used and Adobe was able to negotiate to add Flash directly into the browser. Both Microsoft Edge and Google Chrome are distributed with Flash. These APIS have slowly become more restrictive over time and the future of the web will be plugin-free. Since HTML is finally adding a native form of DRM, the bulk of the major content providers no longer need Flash's proprietary nature to protect their content. This removes the last commercial obstacle which I suspect has been keeping the Flash player alive.

Jeffry, How does this Affect You?

Personally, I spent a couple hours last night playing Bloon Tower Defense one of my favorite casual browser games. I hadn't touched it in years, but I'll miss it when it is finally gone. Professionally, this doesn't affect me all that much. I refactored my business more than five years ago to focus on alternate technologies. In the HTML world, I really like Angular, but I've touched on a lot of different technologies. I never turn down the Flex work that comes my way, and people still find me based on my past history. But, I am not actively pursuing it. If you need help migrating your Flex applications to an HTML5 platform, I'd be glad to help, so reach out and we can discuss.

How does this Affect you?

Adobe will stop distributing the Flash Player in 2020, but the Adobe Flash Platform will live on through Adobe AIR. Given AIR's use as a cross platform mobile app development platform I expect that to be around for a long time. If you still have Flash applications in production, now is the time to start planning a migration of sorts. You have, roughly, 2 years to plan your strategy. What migration strategies can you use?
  • Distribute to the Desktop as an Adobe AIR application. You can use all your existing code and the migration will not take long.
  • Distribute as a Mobile Application with Adobe AIR. This has the benefit of using the same code base, but you'll probably need some UI rework to accommodate for the different screen sizes.
  • Rework to HTML5: You can rework your application into an HTML5 application. You should be able to reuse a lot of your services and database code, which means you'll just be writing a new UI. Some technologies such as FlexJS or Haxe allow you to use your ActionScript skills in the process
I'll be more than happy to help you with any of these tasks, so give me a call.

What Next?

I had a fun ride with the Flex community and met some new lifetime friends. I'm sorry to see Flash go, but the world has moved on. This is just a last reminder that we all have to move on. What do you think? What do you remember most about Flash or Flex?

Can I create an HTML Background with an inline Image?

$
0
0
I'm working on a site for some clients, and one of their complaints was that the left nav bar was not extending the full height of the page. The nav div was set to expand to its content, which meant it stopped when it ran out of content. On some pages it looked fine, on others the nav bar ended too early. As a programmer, I don't often deal with design issues like this, so I pulled in the project's designer and we put our heads together to find a solution. First, the problem was very generically like this:Title Our code was much more complicated, using Flexbox for complicated layouts, but this is simple enough example to demonstrate the problem. We were not able to use a simple height:100% in CSS because some parent containers used Flexbox styling and did not stretch the full height of the page. My designer friend recommended tiling a background image. We can change the CSS for the body tag to something like this: body { margin : 0px; background: top left url(blue1x200.png) repeat-y; } The blue1x200.png is an image with just the color blue in it which has a height of 1 pixel and a width of 200 pixels. The repeat-y clarification tells the browser to repeat this image on the y axis, meaning up and down. This solved our issue, so whatever was happening to the page nav or the page content it would not prevent the left 200 pixels on the page from showing up the same color as the background. Using the url attribute to the background CSS will force the page to spawn another HTTP request to load the image. My designer had a trick for that too. He converted the image to a Base64 string representation and replaced the URL: background: top left url('data:image/png;base64,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') repeat-y; The encoded image looks like a lot of gobblygook, but the browser treats it as an image without having to make a new request to load something from the server. Check out the code.You can use a site like this to convert your image toBase64. If you've been doing Web Development for a long time, this sort of technique is probably not new to you, however I had never seen someone encode the images and include it in-line before. It's a cool technique.

How do I Extend a Background Color the Full Height of a Div with CSS?

$
0
0

Introduction to TypeScript - Part 1

$
0
0
I'm working on a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 2 book. This is the first part of that series.

What is TypeScript?

TypeScript is a strongly typed language which can be used to build web applications. It come with a special compiler that converts the strongly typed language into JavaScript so it can run in a web browser. Since TypeScript is strongly typed, it can offer better tooling than can be used with simple JavaScript. Angular 2 was built using TypeScript and I use it heavily in my Angular 4 book. This article is intended to give you an introduction to TypeScript.

Setup the Project

The first step to creating a TypeScript application is to install the compiler. I'm going to use the Node compiler. First, you'll need to set up the node project. Run this command: npm init And follow the instructions. You'll see something like this: This will create a package.json file that will look something like this: {"name": "01helloworld","version": "1.0.0","description": "Sample TypeScript Project","main": "index.js","scripts": {"test": "echo \"Error: no test specified\"&& exit 1" },"author": "Jeffry Houser","license": "ISC" } Now install the TypeScript compiler: npm install -g typescript You'll see this: With TypeScript installed, you're ready to write your first Typescript application.

Create Your First TypeScript File

Create a file named hello.ts: function echo(message) { return message; } document.body.innerHTML = echo("Hello World"); The purpose of this code is to echo a Hello Word message. The function accepts a string, and returns it. The innerHTML of the document's body tag is set to the results of the function call. This file would be valid JavaScript, but it works fine since TypeScript is a Superset of JavaScript. We can use JavaScript inside of TypeScript easily. We'll improve on this throughout the article as we introduce more TypeScript specific concepts. You can compile this file by running this command line: tsc hello You'll see something like this: You aren't given a lot of feedback, but if you check the directory, you'll see a hello.js file: function echo(message) { return message; } document.body.innerHTML = echo("Hello World"); There isn't a lot of difference between the original file and the compiled file, that is because our main TypeScript file is primarily JavaScript. This is a place to start and over the series we'll expand our TypeScript knowledge.

Test the Application in a Browser

Now it is time to test the application in a browser. Create a page named Index.html: TypeScript Greeter This index file loads the hello.js file, which will cause the document.body.innerHTML assignment to be called, which will run function and return the results: Congratulations! You've created your first TypeScript application.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

Creating Variables in TypeScript - Part 2

$
0
0
I'm working on a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the second part of that series. Check out part 1. An important part of programming is the ability to create variables. Let's turn our "Hello World" Variable into a variable. First, we'll do it the Javascript way and then we'll modify it with some TypeScript.

Create a Variable

This is the original demo from the previous section: function echo(message) { return message; } document.body.innerHTML = echo("Hello World"); We can easily add a variable in here. First, create the variable: var message ="Hello World" The var keyword is the normal way to create a variable in JavaScript. Now, modify the echo() call to pass the variable instead of the string: document.body.innerHTML = echo(message); Recompile the code and it will work just as the previous sample:

Define the Variable with Let instead of Var

TypeScript includes a secondary way to create a variable, using the let keyword instead of the var keyword: let message ="Hello World"; This simple replaces the var command with the let command. Recompile and you'll see the same results. Let is part of the ECMAScript 6 standard, but for maximum compatibility, you probably want to stick to ECMAScript 5 or lower compatibility. The reason to use the let command instead of var is because the two scope differently. When you use var the new variable is created as part of the function block. If the variable is not part of the function block it is added to the global scope of the page. This is why it is considered a best practice for a lot of code to be included in an IIFE. This can cause unexpected results in some cases, such as when you access loop counters inside nested for loops, or have one function embedded in another. The let keyword always scopes at the block level, so each for loop would be considered its' own block. Consider this code: function scopedemovar(){ for(var i = 0; i <10; i++){ console.log('outer i: ' + i); for(var i = 0; i <10; i++){ console.log('inner i: ' + i); } } } scopedemovar(); Although this might be considered nonstandard code because the counter variable for both loops is defined twice and identical it is still perfectly valid. What would you expect the output to be? Try it and run it: You may expect the outer loop to loop 10 times, but it only loops once. That is because the inner loop changes the value of the counter variable and the stop condition triggers the second time the outer loop tries to run. Change the var to let: function scopedemolet(){ for(let i = 0; i <10; i++){ console.log('outer i: ' + i); for(let i = 0; i <10; i++){ console.log('inner i: ' + i); } } } Now, each i variable is scoped to its own for block and they do not interfere with each other: I cut off the full output since it was very long, but you can run the code to see that both the inner and outer loop both execute a full 10 times using the let value.

Add Typing to Variables

An important decision for using TypeScript is to make variables statically typed instead of dynamically typed. We can add a type to the variable definition, like this: let message : string ="Hello World"; We can change the function definition too: function echo(message:string ):string { return message; } The function now includes a typed argument and an explicit return type. When we send in the message variable the compiler checks to make sure that we are sending in a string. Recompile the code and run it. You'll see no differences in the output: Open up the JavaScript file created by the TypeScript compiler for a bit of a surprise: function echo(message) { return message; } var message = "Hello World"; document.body.innerHTML = echo(message); All your type statements were stripped out. That is because these types are part of TypeScript, but not JavaScript. They allow for compile time checking of values, but do not change the underlying language or how things run in the browser. This is an important distinction to remember as you learn TypeScript. The language is all about improved tooling and compile time validation; not about a new language in the browser.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

Enums in TypeScript - Part 3

$
0
0
I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the third part of that series. Check out part 1 and part 2. This article will focus on Enums, a TypeScript data type that does not exist in JavaScript.

What is an Enum?

Enums are a data type I have not come across in most other languages, but they are inspired by C#. An enum is a way to give friendly names to numerical values. They are like an array with indexes, but more specific. I can envision using something like this with a view stack style component and using an enum to handle which view is currently displayed. Or, I might use it with an event class instance to determine what type of event occurred. Or it could be used to determine what color style to apply to certain text.

Create a Number based Enum

I'm going to start by creating a simple sample with a number based enum: enum MyNumbers { First, Second, Third } The MyNumbers enum contains four values each one representing a number. Since enums are sort of like arrays, the First item is at the 0 index, the second item will have the value of 1, and so on. We can use MyNumbers like it was it's own variable type: let myNum :MyNumbers = MyNumbers.First; Output this value. console.log(myNum); What do you think you'll get? Since it is the value of MyNumbers.First and that is the first element of the zero-based index, you'll get number 0: A benefit of enums is that we can control the number scheme: enum MyNumbers { First = 1, Second, Third } We specified the First item is equal to the number 1. Turn each element into a variable: let myNum1 :MyNumbers = MyNumbers.First; let myNum2 :MyNumbers = MyNumbers.Second; let myNum3 :MyNumbers = MyNumbers.Third; Then output them: console.log(myNum1); console.log(myNum2); console.log(myNum3); You'll see: Now our text numbers match up with the actual text index. We can control the numbers even if they aren't in sequential order. Add a new entry to the MyNumbers enum: enum MyNumbers { First = 1, Second, Third, Ten = 10, } This is number 10, skipping four through 9. Grab it as a variable and output it: let myNum10 :MyNumbers = MyNumbers.Ten; console.log(myNum10); Combined with our other outputs, you'll see something like this: Enums provide a lot of flexibility. Enums can also be created to use a string based index, and we'll discuss that in the next article.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

String Enums in TypeScript - Part 4

$
0
0
I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the fourth part of that series. Check out part 1, part 2, and Part 3. This article will focus on creating String based Enums.

What is an Enum?

Enums are a data type I have not come across in most other languages, but they are inspired by C#. An enum is a way to give friendly names to numerical or string values. They are like an array with indexes, but more specific. I can envision using something like this with a view stack style component and using an enum to handle which view is currently displayed. Or, I might use it with an event class instance to determine what type of event occurred. Or it could be used to determine what color style to apply to certain text.

Create a String based Enum

It is interesting that Enum's can be used to represent textual values too. Look at this: enum MyColors { Blue = "#0000FF", Red = "#FF0000", Green = "#00FF00", }; The value of the color name represents the hex value of the actual color. I recently could have used something similar when dynamically applying colors to the header of a site based on which section the user was viewing. Get the individual colors, and output them: let myColor1 :MyColors = MyColors.Blue; let myColor2 :MyColors = MyColors.Red; let myColor3 :MyColors = MyColors.Green; console.log(myColor1); console.log(myColor2); console.log(myColor3); You'll see something like this: Enums are an interesting data type, caught somewhere between an array and a class.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

Loops and Arrays in TypeScript - Part 5

$
0
0
I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the fifth part of that series. Check out part 1, part 2, Part 3, and Part 4. This entry will focus on loops and arrays. We'll create an array of strings, and then loop over them with our echo function to welcome multiple people in our HTML page.

Create an Array

The first step is to create an array. You can use this sytnax: let personArray : string[] = ["Jeffry", "Tom", "John"]; This creates a variable just like other variables we had seen. The key differentiator is that after the type, I added square brackets. This is what tells the compiler we are creating an array of strings. You can define arrays with any of the native types, such as numbers or Boolean, or with your own custom types.

For-in Loop

The very first time I wanted to loop over an array, I used a for-in loop, like this: let bodyString : string = ""; for (let person in personArray){ bodyString += echo(messageIntro + "" + person + "
"); } document.body.innerHTML = bodyString ;
I had used for-in loops in other languages, such as ActionScript so this was my natural impulse. Let's look at the results: Instead of outputting the data in the array, it outputted the index. The proper way to use a for-in loop in TypeScript would be like this: for (let person in personArray){ bodyString += echo(messageIntro + "" + personArray[person] + "
"); }
This isn't much different than a generic for loop that uses a counter, although the syntax is a bit nicer: All version of ECMAScript after 2015 support for-in loops the same way that TypeScript does. This is supported by most browsers and in fact that generated JS Code uses for-in loops: for (var person in personArray) { bodyString += echo(messageIntro + "" + person + "
"); }
But, this result wasn't quite what I was after. Thankfully TypeScript includes another option, the for-of loop.

For-Of Loops

A for-of loop makes one syntactical difference than a for-in loop. Instead of using the keyword in, it uses the keyword on: for (let person of personArray){ bodyString += echo(messageIntro + "" + person + "
"); }
This type of loop the loop counter, person, will match the value of the personArray instead of the index. After the compilation this is turned into a for loop with an explicit counter: for (var _i = 0, personArray_1 = personArray; _i < personArray_1.length; _i++) { var person = personArray_1[_i]; bodyString += echo(messageIntro + "" + person + "
"); }
Compile this code and load it in the browser to see the expected results: Looping in TypeScript is not much different than looping in other languages. The next entry in this series will focus on creating classes.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

Create your first TypeScript Class - - Part 6

$
0
0
I'm writing a series of articles about Typescript as extra material to support my upcoming Angular 4 book. This is the sixth part of that series. Check out part 1, part 2, Part 3, Part 4, and Part 5. This entry will teach you about creating your own classes. A class is like your own variable type with data and functions to process that data.

Create a Class

Create your class stub: class Echo { } This creates a class named Echo. The purpose of this class is to create and store our welcome message. Let's start by creating some properties on the class: static readonly messageIntro : string = "Hello" subject : string; private message : string; The subject is a relatively normal variable. It is a string that contains the subject of our welcome message. The message is similar, but has the private distinguisher. This means that the message variable is private to the local message. It will contain the final message once it is put together, but is only accessible inside the class, not from code accessing an instance of the class. The messageIntro is a bit different. We are not able to define constants inside of a TypeScript class, so instead I used the readonly keyword. This means the value will not be changeable, just like a constant. I also define the messageIntro as a static property, which means it exists on the class and not on an instance of the class. Every class needs a constructor, so create one: constructor(subject : string){ this.subject = subject; } The constructor will be called automatically when we create a new instance of the class with the new keyword. This constructor accepts one argument, the subject. The code just saves the subject argument into the subject variable. Now, add a createMessage() function: createMessage():void{ this.message = Echo.messageIntro + "" + this.subject + "
"; }
This concatenates the read only messageIntro variable with the subject and a line break. We had similar code in previous samples, but not encapsulated into a function. The return type of this function is void, meaning nothing is returned. We'll add one final function to our class: echo():string{ return this.message; } This function returns the complete message. The message value could be blank if the createMessage() function as not called yet, however this will still work. Now, create an instance of the Echo class: var echoInstance : Echo = new Echo('World') This uses the new keyword to create the new instance. You may have seen this in other languages. You can output the subject for testing purposes: console.log(echoInstance.subject); You can also try to output the message: console.log(echoInstance.message); Since the message is a private variable, you'll see a compile error: By the same token, we can access the messageIntro static value: console.log(echoInstance.messageIntro); console.log(Echo.messageIntro); Can you guess which line works before trying to compile the code? The second one is the proper way to access static variables. The first one will throw an error: Our final code is to output the value to the screen: document.body.innerHTML = echoInstance.echo(); Compile the code--you should see no errors--and load it in a browser: In a non-sample application, I might try to make my classes more discrete. Since this one adds a line break at the end of the message, it is conflating data processing and display code, something which is undesirable in real world applications.

Review the Generated Code

This is the generated code: var Echo = (function () { function Echo(subject) { this.subject = subject; } Echo.prototype.createMessage = function () { this.message = Echo.messageIntro + "" + this.subject + "
"; }; Echo.prototype.echo = function () { return this.message; }; Echo.messageIntro = "Hello"; return Echo; }()); var echoInstance = new Echo('World'); echoInstance.createMessage(); document.body.innerHTML = echoInstance.echo();
The Echo class is created using an immediately invoked function expression. The static class property is created as an instance variable inside the class--remember that JavaScript doesn't have the concept of readonly or static properties. The subject and message variables are not defined since they do not have default values. They'll be created on the class when they are needed, which is inside the function. Although beyond the scope of this tutorial, inheritance is supported with TypeScript, so one class can inherit from another.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

Create an Interface in TypeScript - - Part 7

$
0
0
I'm writing a series of articles about Typescript as extra material to support my upcoming Angular 4 book. This is the seventh part of that series. Check out part 1, part 2, Part 3, Part 4, Part 5. and Part 6. This section will talk about interfaces. It is not about User interfaces, but rather object-oriented interfaces. An interface is a definition of properties and methods that must be supported by a class which implements this interface. You can think of an interface as the contract between a class instance and a method argument or variable. If they both match the interface they are interchangeable.

Create the Interface

For this sample, we're going to create a name interface. This interface will represent the name of a person and will contain a first name and last name. It will have an optional middle initial and also a method to retrieve the name. Here is the interface: interface name { firstName: string; middleInitial? : string; lastName: string; getName() : string; } The interface is set up similar to a class or enum. It uses the keyword interface, and the name of the interface--in this case name. The firstName and lastName properties are as normal properties on an object. The middleInitial is an optional property, and that is distinguished by a question mark. Finally, a single method is defined by the interface, getName(). This will be used to return the name. The interface does not contain an implementation, just a definition of the method. That means different classes which extend the interface can have different implementations.

Rework the Echo Class

Let's rework the Echo class to use the interface instead of strings. First create the method stub with the instance variables: class Echo { static readonly messageIntro : string = "Hello" subjectArray : name[]; private message : string; } The main change here is that the subject string was replaced with a subjectArray of name types. The constructor: constructor(subjects : name[]){ this.subjectArray = subjects; } The constructor now accepts an array of name instead of a single string. The createMessage() function now loops over the array: createMessage():void{ this.message = ''; for (let person of this.subjectArray){ this.message += Echo.messageIntro + "" + person.getName() + "
"; } }
Inside the loop, the interface's getName() function is used to add an element to the output. Finally, the echo() function: echo():string{ return this.message; } The echo function has not changed, it just returns the object instance variable, message.

Implement the Interface with a Class

I'm going to create two classes which implement our name interface contract. One will be for a Person and another for a Pet. First, the Person class: class Person implements name { firstName: string; middleInitial : string; lastName: string; getName(): string { return this.firstName + '' + this.middleInitial + '' + this.lastName; } } The class is defined with the class keyword followed by the name of the class. Then comes the implements keyword followed by the name of the interface. If you wanted you could list multiple interfaces here. The firstName, middleInitial, and lastName are created properties on the object, not much different than how they were with the interface definition. The getName() method includes a definition. It concatenates the firstName, middleInitial, And lastName, returning a single string. Now, let's create another class that implements name. This one is called Pet: class Pet implements name { firstName: string; lastName: string; type : string; getName(): string { return this.firstName + '' + this.lastName + ", " + this.type; } } This includes the firstName and lastName defined as variables on the class object. A new property is named type, this will represent the type of pet we have. A class can implement properties or methods not included in an interface. The middleInitial is left out, which is okay because that is marked as an optional property in the interface--and my pets don't have middle initials. The getName() method puts together the firstName and lastName, but appends the type to the end.

Create a name Array

We have an interface and two classes that extend it. Let's put all together. Start by creating a names array: let nameArray : name[] = []; Now create a new Person instance. This one represents me: let jeffryInstance : Person = new Person(); jeffryInstance.firstName = "Jeffry"; jeffryInstance.middleInitial = "A"; jeffryInstance.lastName = "Houser"; nameArray.push(jeffryInstance); The new jeffryInstance of the Person class is added to the nameArray. Create two pets: let hercInstance : Pet = new Pet(); hercInstance.firstName = "Hercules"; hercInstance.lastName = "Houser"; hercInstance.type = "Dog"; nameArray.push(hercInstance); let zeusInstance : Pet = new Pet(); zeusInstance.firstName = "Isadora"; zeusInstance.lastName = "Houser"; zeusInstance.type = "Dragon"; nameArray.push(zeusInstance); One is for my pet dog, Hercules, and the other is for my pet dragon, Isadora. Both are added to the same nameArray value without issue even though they have different types. The implementation of the interfaces tells the compiler that the nameArray can accept both Pet and Person instances. Now, create an instance of the Echo class: let echoInstance : Echo = new Echo(nameArray); Create the message: echoInstance.createMessage(); And output the message: document.body.innerHTML = echoInstance.echo(); Recompile the app and load it in a browser: It works as expected. I have one more entry into this introduction to TypeScript series. It will tell you how to create Modules from your class and interface files.
Keep up to date by reading DotComIt's Monthly Technical Newsletter

Create TypeScript Modules - - Part 8

$
0
0
This is the last in my series of articles intended to introduce you to Typescript. It is bonus material I wrote for my Angular 4 book. This is the last part of the series. Check out part 1, part 2, Part 3, Part 4, Part 5. and Part 6, and Part 7. When writing a real-world application, it does not make sense to include all the code in a single file. TypeScript supports that by allowing you to expand different functionality into modules.

Create Interface Module

The first thing we're going to do is create a module for the name interface. I put this in a file named IFile.ts: export interface name { firstName: string; middleInitial? : string; lastName: string; getName() : string; }; This looks exactly like the Interface created in the previous exception with the one addition of the export keyword. Export tells the compiler that this class is available for use inside other classes.

Create Class Modules

Now create the Person class: export class Person implements name { firstName: string; middleInitial : string; lastName: string; getName() : string { return this.firstName + '' + this.middleInitial + '' + this.lastName; } } This also puts the export keyword in front of the class definition. If you try this you'll notice an immediate error. The name is not defined. To define it we'll need to add an import statement: import {name} from "./IName"; The import statement tells you that the name entity is imported from the IName file and can be used within this class. The path I used, './IName', tells us that the files are in the same directory, however we can use a more elaborate package setup, and most likely you will do that for main applications. We can create the Pets.ts module in the same manner: import {name} from "./IName"; export class Pet implements name { firstName: string; lastName: string; type : string; getName() : string { return this.firstName + '' + this.lastName + ", " + this.type; } } This code mirrors the Person module, with the primary changes being the use of the export keyword before the class definition and the import of the name interface. The Echo class needs a similar rework: import {name} from "./IName"; export class Echo { static readonly messageIntro : string = "Hello" subjectArray : name[]; private message : string; constructor(subjects : name[]){ this.subjectArray = subjects; } createMessage():void{ this.message = ''; for (let person of this.subjectArray){ this.message += Echo.messageIntro + "" + person.getName() + "
"; } } echo():string{ return this.message; } }
The functionality remains unchanged. Like the previous classes it uses an export statement to make the class available elsewhere, and an import statement to make use of the name interface.

Rework Main Application

With all the classes stored in separate files, our primary app has become a lot simpler. First, import all the classes: import {name} from "./IName"; import {Person} from "./Person"; import {Pet} from "./Pet"; import {Echo} from "./Echo"; Then, create the nameArray: let nameArray : name[] = []; Now, populate the nameArray: let jeffryInstance : Person = new Person(); jeffryInstance.firstName = "Jeffry"; jeffryInstance.middleInitial = "A"; jeffryInstance.lastName = "Houser"; nameArray.push(jeffryInstance); let hercInstance : Pet = new Pet(); hercInstance.firstName = "Hercules"; hercInstance.lastName = "Houser"; hercInstance.type = "Dog"; nameArray.push(hercInstance); let zeusInstance : Pet = new Pet(); zeusInstance.firstName = "Isadora"; zeusInstance.lastName = "Houser"; zeusInstance.type = "Dragon"; nameArray.push(zeusInstance); Create an instance of the Echo class: let echoInstance : Echo = new Echo(nameArray); Call the createMessage() function: echoInstance.createMessage(); Finally, output the results: document.body.innerHTML = echoInstance.echo(); The changes here was, primarily, removing the class and interface definitions and replacing them with imports.

Setup Module Loader

The import statement is not a native JavaScript statement and does not have an easy parallel. To make code like this work in the browser we'll need to use a module loader. There are a few different types of module loaders such as RequireJS or SystemJS. Many people use code tools like Browserify or WebPack to encapsulate away the complexity. For the purposes of this sample, I'm going to use RequireJS. Open up the index.html file and add this script statement: This loads the RequireJS library from a remote CDN. Note that I have completely removed the script tag that loads the hello.js file. The script tag also has a different attribute named data-main with a value of requireconfig. This property tells Require that whenever it has completed loading it should look for the requireconfig.js file. Create that file next: requirejs.config({ baseUrl: '', paths: { app: '' } }); This sets up the baseUrl and the paths to the app. Since all our code is in the main dev directory, I set these values to blank. Now, tell RequireJS to load our main application file: requirejs(['hello']); Since there are a few different methods of creating modules, we have to tell our TypeScript compiler which one to use. We want it to use the amd approach. When you compile your application add the module flag and specify amd. Use this at the command line: tsc –module amd hello You'll see this: Now load the app in the browser: Congratulations! This series should have given you all the information you need to know to start using TypeScript to build your applications. Check out our book on Angular 4 which uses TypeScript heavily.
Keep up to date by reading DotComIt's Monthly Technical Newsletter
Viewing all 497 articles
Browse latest View live