Check out our Angular Book Series.

Learning Redux - Saying Goodbye to Hello World - Part 3

This is the third part in a series on Redux, a state Management Framework used with single page application frameworks such as React and Angular. This article series looks at using Redux without another framework. Please read part 1, and Part 2 before reading this.

I write about Redux and Angular in the bonus book to the Angular 6 series.

This article will expand on the previous "hello world" sample to teach you how to say Goodbye.

Add a new state to the Reducer

With every hello comes a goodbye. We are going to create a button that will say goodbye to the user, and then clear out the helloUser value from the store. The purpose of this sample is to add more objects in the store.

First, let's start with the UI:


<button id="goodbyebtn">GoodBye</button><br/><br/>
GoodBye <span id="goodbyeValue"></span>

I added a Goodbye Button, and a span for the goodbyeValue. Back to the JavaScript, handle a click on the goodbyebtn:


document.getElementById('goodbyebtn')
.addEventListener('click', function (e) {
store.dispatch({ type: 'NAME_LEFT',
value : store.getState().helloUser})
})

This dispatches an action. The type is NAME_LEFT. The value is the current helloUser.

Let's go back to our reducer function and add some code to handle this new action:


case 'NAME_LEFT':
newState.goodbyeUser = action.value;
newState.helloUser = '';
break;

It is just another case statement in the switch. We set a new value on the state to goodbyeUser, and set the helloUser value to an empty string. When we set the default, near the beginning of the reducer() method, be sure to initialize the goodbyeUser state property:


if (typeof state === 'undefined') {
newState = {
helloUser : '',
goodbyeUser : ''
}
}

Now we need to create a function to render the code:


function renderGoodbye() {
document.getElementById('goodbyeValue').innerHTML =
store.getState().goodbyeUser.toString()
}

This just uses getElementByID() to get the span for the goodbyeValue. It sets the innerHTML to the stores goodbyeUser property. Make sure you subscribe: store.subscribe(renderGoodbye)

The code should be runnable now:

Enter your name and you'll "Hello Jeffry", just as with our original sample. Then click the GoodBye button, and you'll see the name populate after Goodbye and the name after Hello blank out. I did not add code to blank out the user input, but you should be able to do that easily if needed.

Play with a live sample here.

Learning Redux - Vanilla JavaScript Sample - Part 2

Redux is a state Management Framework that is primarily used with React, but can also be used with Angular. This article series looks at using Redux without another framework. Please read part 1 before reading this.

I write about Redux and Angular in the bonus book to the Angular 6 series.

This article will show you how to write your first Redux application. We're going to create a simple Hello World style sample.

Set up the Infrastructure

Create a new blank HTML Page. It'll look something like this:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redux Vanilla JS</title>
</head>
<body>
</code>
</body>
</html>

Import the Redux library:


<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.0/redux.min.js">
</script>

Instead of using NodeJS and Build Script tools, I'm just pulling it out from an Internet based CDN because it is the simplest way. Create the reducer:


<script>
function reducer(state, action) {
}
</script>

The reducer is the function that will run when actions are dispatched to the store. It takes in the current state and the action, then runs code to determine what the new state will be. A reducer should not have any side effects. That means it should not modify the existing state. The first step is to make a copy of the existing state:


var newState = Object.assign({}, state)

On first run of the application, no existing state will be defined, so we'll check for that and set some defaults:


if (typeof state === 'undefined') {
newState = {
helloUser : ''
}
}

The state of the application is just a JavaScript object. I included one property on that object, helloUser and defaulted it to an empty string. Once we start dispatching events, we'll revisit this function to handle those event types. Until then, just return the new state:


return newState;

That completes the reducer, for the moment.

Now, create the store:


var store = Redux.createStore(reducer);

This calls the createStore() value on the Redux library. The reducer() function is passed in. Notice we are saving the store as a local variable for future reference. Do not put this line of code inside the reduce.

Let's create our simple UI:


Enter Your Name: <input id="username"><br/><br/>
Hello <span id="helloValue"></span>

We're going to set this up so that when the user types in the input, the text will automatically update in the span. I've seen similar samples used to demonstrate how binding works in Angular.

Let's switch back to JavaScript and create a function to render the UI:


function renderHello() {
document.getElementById('helloValue').innerHTML =
store.getState().helloUser.toString()
}

The renderHello() function accepts no arguments. It uses the JavaScript document object and getElementByID() function to retrieve the helloValue span. Then it populates it with the helloUser string in the state. We retrieve the state from the store using the getState() functionality. Be sure to call the renderHello() function immediately to render the function in the default state:


renderHello()

Whenever the state changes, we want to run this renderHello() function. We do that with the subscribe() function on the Redux store:


store.subscribe(renderHello)

Now, when the state changes, the renderHello() function will be called, thus causing the UI to update.

Whenever the username input is modified, we want to dispatch an action to the store so that the reducer() function runs, which will return the modified state, and then run the renderHello() listener to modify the UI. This is the code:


document.getElementById('username').addEventListener('keyup', function (e) {
store.dispatch({ type: 'NAME_MODIFIED', value : e.target.value})
})

Without a framework, such as Angular, it is a bit complex to listen for events on elements, but we grab the username input with getElementByID() and then listen for the keyup event. We use store.dispatch() to send a NAME_MODIFIED action. By convention, the type of the action is a constant put in all caps, but here we are hard coding it a bit.

We need to modify the reducer() function to handle the NAME_MODIFIED action:


switch (action.type) {
case 'NAME_MODIFIED':
newState.helloUser = action.value
break;
default:
// do nothing
}

This code is after the undefined check, and before the return statement. It is a switch statement that checks for the action's type, and does actions based on that. At this stage in the application, we only have a single event, but we'll add one more as we iterate over this code.

You should be able to run the code now:

As you type your name the text will appear after the hello.

Play with this sample.

And don't forget to pick up the Angular 6 books from the Learn With series.

Learning Redux - Definitions - Part 1

Redux is a state Management Framework that is primarily used with React. There is an Angular port of it, ngrx. I wanted to learn a bit about Redux and write about it in the latest Bonus book for my Angular 6 series.

This is the first in a series of articles about Vanilla Redux. In this article we'll talk a bit about terminology used for Redux and how a Redux application should flow.

Understanding Redux Terminology

Many frameworks have their own terminology, so this section will explain some common terminology.

  • Actions: Actions are a collection of data that you send to the Store. The object must have a type value to define the type of action. The action in Redux is similar to the EventEmitter you've probably used in your Angular applications, and are passed to the store using a dispatch() function.
  • Action Creators: Action Creators are functions that return an action. Action Creators do not dispatch the action, only return it. It is a way to encapsulate your functionality for creating an action.
  • Reducers: Reducers are a function that update the state of the application. It accepts the current state, and the action you are performing. Reducers should be pure functions, meaning they do not have any side-affects such as changing the arguments or calling non-pure functions. The reducer does not change the current state of the application because that would be a side effect. It only creates, and returns, a new state object.
  • State: The state is an object that stores data for your application, such as items in a shopping cart, the user who logged in, or other information.
  • Store: The store is a single object that holds all the application state. It can return the state using a getState() function. It registers or unregisters listeners using a subscribe() function. And it updates state via dispatch() function.

As we progress through this series, we'll cover each item in more detail.

Understanding Redux Flow

Redux has a unidirectional data flow. That means that data always flows in one direction throughout the app. I put together a diagram: Let's look at each box:

  1. Start in the top middle. You have a view which is waiting for action. This could be a user entering data or clicking a button. Technically this doesn't even have to be a view but could be any code in your app, such as the result handler of a remote service call.
  2. When an action occurs, the view will call the dispatch() method on the store and send in the action object.
  3. The store will, in turn, call the reducer() function. The current state and the new state are passed in as arguments. The reducer function will do some magic and return the app's new state.
  4. The store saves the new state.
  5. Then the store calls any listener functions. At some point your code must have called store.subscribe() so it could get notified when something changed.
  6. The listener functions run code and update the view. If they need access to the current state they can call the getState() method on the store.

The process is simple to understand. With a shared vocabulary, we're ready to tackle some code and the next article in this series will create the first Vanilla JavaScript Redux sample.

How do I combine Objects in JavaScript? Use the Ellipsis Operator!

This is a followup to last week's post about using Object.assign() to combine two JavaScript objects. Today I'll show you how to use the spread, or ellipsis, operator to do the same thing.

The scenario is that we have a configuration object being passed into a method. A lot of the config values are optional, and we want to default them if they are left out before the method does it's magic. We could write a lot of manual conditions to accomplish this, like this:


function conditionalConfig(config){
if(!config.option1){
config.option1 = defaultOption1Value;
}
if(!config.option2){
config.option2 = defaultOption2Value;
}
// etc.. etc.. etc..
// do other stuff
}

The code works, but it is tedious to write. We can use the Spread Operator to simplify it.

The Spread Operator

The spread operator is an ellipsis, or three dots. It has a handful of uses, but today I'm going to show you how to combine two objects.

Start with a function and an object that contains all the default values:


function defaultConfigWithSpread(config){
defaultObject = {
option1 : 'DefaultValue1',
option2 : 'DefaultValue2',
option3 : 'DefaultValue3',
option4 : 'DefaultValue4',

Notice I didn't close the object yet. We have one more property to add to the object:


...config
}

That last property is our spread operator. It tells the underlying engine to take all the properties from the config object and copy them into the defaultObject. If a property already exists in the defaultObject, it is overwritten. If a property does not exist it will not be changed.

For demonstration purposes, log the two objects:


console.log(config);
console.log(defaultConfig);
// do other stuff
// end function
}

You can test this like this:


customConfigObject = {
option1 : 'Value1',
option2 : 'Value2',
option3 : 'Value3',
}
defaultConfigWithSpread(customConfigObject);

Look at the console output and you'll see that the original config object is unchanged, but the default object contains all the new values:

The custom values from our config argument are retained and the unset default value--option4--is set with the new config.

You have to be careful when doing this to keep around a clean version of the default object since it is modified with this approach. I addressed that by creating the default config inside the function, as opposed to some permanent store.

Play with the code here.

It is a nice shorthand to be aware about.

How do I combine Objects in JavaScript? Use object.assign()!

Let's say we have a config object being passed into a method. A lot of the config values are optional, and we want to default them if they are left out before the method does it's magic. The structure is like this:


function conditionalConfig(config){
if(!config.option1){
config.option1 = defaultOption1Value;
}
if(!config.option2){
config.option2 = defaultOption2Value;
}
// etc.. etc.. etc..
// do other stuff
}

The code works great, but it is tedious to write all those conditionals. Is there a way to simplify it? Yes there is and I'm going to talk about two ways to do that. Today we'll cover object.assign().

Object Assign

The first way to simplify this code is to use object.assign(). Object.assign() will copy all the values from one object into another. First, create an object instance with all the default values:


function defaultConfigWithAssign(config){
defaultObject = {
option1 : 'DefaultValue1',
option2 : 'DefaultValue2',
option3 : 'DefaultValue3',
option4 : 'DefaultValue4',
}

Now use Object.assign() to combine that with your function argument:


Object.assign(defaultConfig,config)
// dump to console for testing purposes
console.log(config);
console.log(defaultConfig);
// do other stuff
// end function
}

You can test this like this:


customConfigObject = {
option1 : 'Value1',
option2 : 'Value2',
option3 : 'Value3',
}
defaultConfigWithAssign(customConfigObject);

Look at the console output and you'll see that the original config object is unchanged, but the default object contains all the new values:

The custom values from our config argument are retained and the unset default value--option4--is set with the new config.

You have to be careful when doing this to keep around a clean version of the default object since it is modified with this approach. I addressed that by creating the default config inside the function, as opposed to some permanent store.

Play with the code here.

Next week I'm going to talk about the Spread operator which can be used to accomplish the same thing.

How do I run ES6 JavaScript code on the console?

I've been following a tutorial on using Redux and the code in the sample is ES6 code. The tutorial ran the code in the debugger of Visual Studio Code, but me being an IntelliJ user could not find an parallel way to run the code.

I created an Index.html file that loaded the JS file, but nothing happened. I assume because the ES6 syntax used in the sample as not yet universal in the browser JS engines.

So, what next? I looked for a way to run the code at the console, and found one. With NodeJS installed:


node filename

That ran the code, and gave the same results that the tutorial got in the Visual Studio Code window. After doing that, I realized I could run the same thing in IntelliJ's terminal Window.

I'm not used to running advanced JS or TypeScript code w/o transpiling it with a tool like TypeScript, Webkit or the Angular CLI. This project started simpler, but I'm good to go now.

I hope this helps you!

How do I fix IE11 problems with CSS Calc and min-height?

I hate it when you have a problem that you cannot replicate in a simple example. That's exactly where I am. I'm working on an application built with HTML, CSS, and various JavaScript frameworks. The application requires a footer to be aligned at the bottom of the page. If the content is too large for the page, then the the footer should show up under the content. But, if the content is too small for the page, the footer should show up at the bottom of the window, or viewport.

This should be pretty simple to build using CSS and HTML:


<div class="wrapper">
Lots of Main Content and navigation and headers Here
</div>
<footer>
Some Footer Information Here that should always be at the bottom of the page
</footer>

The CSS would be something like this:


html, body {
height: 100vh;
margin : 0;
}

.wrapper {
min-height: calc(100% - 200px);
}

footer {
height : 200px;
background-color : blue;
}

The actual client project code is a lot more complex, but this gives you the gist. Play with the code here. Ignore my design skills.

The problem I was having was that IE11 seemed to have a problem with the min-height. When clicking in the page, or clicking a link to go to another page, it was as if the wrapper's min-height would shrink down on pages where the view height was greater than the actual content. This would cause the footer to jump to the middle of the page.

For the life of me, I haven't been able to create a simple sample to demonstrate this. Some part of the client's custom code seems to be causing this.

After some head banging and conferring with my team, I came up with this solution. It makes use of JavaScript and JQuery to 'hard code' the min-height on the wrapper. Instead of using the CSS Calc. this happens when the page loads and whenever the page is resized.


if(/MSIE \d|Trident.*rv:/.test(navigator.userAgent)){
function onResize(){
     /* The jquery calc code */
     $('.wrapper').css('min-height', '100%').css('min-height', '-=200px');
}

$(window).resize(function() {
onResize()
});

$(window).ready(function(){
onResize()
});

}

I used a regex trick to only execute the code for IE browsers. And I used this answer as a base for my solution.

Part of our problem solving this was my inability to create a simple reproducible case, but pouring over thousands of line of code I could not find the magic style combination that caused the 'footer jump' problem.

Frustrating; but the JS code above seems to solve the issue admirably.

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

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:

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

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.

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

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.

More Entries

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.