Check out our Angular Book Series.

How do you override a method in JavaScript?

I'm working on an experimental project and wanted to find out if I could override a method in JavaScript. I wanted to see if I could override the JSON.stringify() method to add my own functionality. It turns out you can and it is pretty easy.

First, let's create an object we want to convert to JSON:


let myObject = {
foo: "bar",
foo2: "bar2",
foo3: "bar3"
}
console.log('------ JSON.stringify output ---------');
console.log(JSON.stringify(myObject));

Output that to make sure all is good:

Now, let's may a backup copy of JSON.stringify:


let myJSONStringifyCopy = JSON.stringify;
console.log('------ My Copy output ---------');
console.log(myJSONStringifyCopy(myObject));

This is just a new variable that references JSON.stringify() and we can use it just as we would JSON.stringify():

Okay, but now we want to replace JSON.stringify(). Create our own method:


function myOwnReplacement(value) {
return "faker";
}
JSON.stringify = myOwnReplacement;

console.log('------ JSON Stringified Replace ---------');
console.log(JSON.stringify(myObject));

console.log('------ My Copy output ---------');
console.log(myJSONStringifyCopy(myObject));

Will overwriting JSON.stringify also overwrite our myJSONSTringifyCopy? Nope as these dumps prove:

Play with the sample here.

In the case of this replacement it isn't very useful, especially since the resulting output is no longer JSON. But, I'm working on something slightly more interesting that I hope to be able to share at some future point.

Note: I do not endorse doing this to your friend's application on April Fools day, unless you really want to.

Why didn't my Angular View Update when I added items to the input array?

I was recently working on an Angular project where the view had an input array:


@Input() items: Array<items>;

The view of the component would loop over the array:


<div *ngFor="let item of items">
{{ item.data }}
</div>

At some point in the app, user interaction happens, and the app needs to load more data. We had a result handler from a service call doing something like this:


items.push(...itemsToAdd)

If you output the results, you'll see that the items array had the new items. Try it here.

However, the view would not update the display to reveal the new items in the array. How come?

In short, the view did not know that it needed to update itself. The view contains a pointer to the array and was watching for changes to that pointer. While the items in the array changed, the array pointer did not. An easy solution was to change the way items were added to the new array:


items = items.concat(itemsToAdd)

Since we were updating the actual input value, the view would know that the item had changed, triggering a redraw of the screen.

That's how we handled it!

How to fix the "definition not supported by current JavaScript version" error in IntelliJ

I put together this screencast to show you how to fix the 'not supported' error in IntelliJ that I often see when creating new projects.

How do I get an Array of all the Keys in a JavaScript Map?

I'm working on an Angular application and want to loop over all the keys in a JavaScript map. A map is a key value pair data type, like an object, but geared for dynamic properties. In the ColdFusion world we called this a structure, and in ActionScript we called it a dictionary, but the concept is the same.

I can create a map and add items to it, like this:


let myMap = new Map();
myMap.set('foo', 'bar');
myMap.set('bar', 'Barbar');
myMap.set('foobar', 'BarbarFooFoo');

You can look at the map like this:

Once it has a set of keys, I can get the keys using this:


myMap.keys();

This is an object, or more specifically an iterator. But, I want the keys as an array.

One trick is to convert the iterator to an array using Array.from():


Array.from( hydratedImageMap.keys() );

A more 'ES6' technique would be to use the spread operator:


[ ...hydratedImageMap.keys() ]

You'll see similar output:

Not all that hard! Get the code here or play with it here.

How do you deep copy an array with JavaScript?

The Problem

I was working on an Angular component that accepted an array input and created a drop down from it. As part of our internal architecture the component would add a disabled property to certain items on the input. This would permanently modify the input array, which was cached by the app and used elsewhere. We couldn't have that. We decided to make an internal copy of the array so that our local component changes would not affect the global data store. How do we do that?

Normally when I want to create a deep copy of an object, I turn to Try it here


const object1 = [
{value: 1},
{value: 2},
{value: 3}
];

const object2 = Object.assign({}, object1);

console.log(object1);

console.log(object2);

Take a look at the output:

If you look closely at the output between object 1 and object 2, you'll discover that object2 is no longer an array, it is an object. That was the wrong syntax and not what we intended.

Object.Assign() with an Array

We could use Object.assign() with an array instead of an object, like this:


const object3 = Object.assign([], object1);

That will give us an array. Make sure that they are separate objects:


object1.push({value:4})
console.log(object1);
console.log(object3);

That does solve the issue and we have an array:

It isn't the only way to solve the issue, though.

Use a spread operator

The spread operator will do the same thing.


const object4 = [...object1];
object1.push({value:4})
console.log(object1);
console.log(object4);

I always forget about the spread operator, but it works well. Depending where you look, there are concerns about it's performance over other options. I'm reusing the same screenshot because there is no change:

Use Slice

You can also create a deep copy of an array using array.slice():


const object5 = object1.slice();

object1.push({value:4})

console.log(object1);
console.log(object5);

Repeated screenshot because nothing changed:

This is the way I went with, for no other reason than it was used elsewhere in the code base and it pays to be consistent.

Hopefully you learned something. ;)

Why won't my Template Strings work?

As you probably know, I have been doing a lot of work with Angular, TypeScript, ES6, and the surrounding ecosystem. I've started using template strings a bunch.

This was the old way to create a string from many variables:


myNewValue = "http://" + myDomain + myPath + "?value=" + myValue;

It worked but got tedious. ES6 introduced something called template strings. Instead of using all those plus signs to concatenate variables, we can do use a friendly syntax:


myNewValue = `http://${myDomain}${myPath}"?value=${myValue}`;

I've read about this, done a few proof of principle samples, but for the first time I'm actually using this on a project and integrating it with code.

These are the two mistakes I make most common.

Use the Grave Accent

A template string must be enclosed in a grave accent, or backtick. This is the same key you use when formatting inline code in a StackOverflow comment or inside Slack. If you use double quotes or regular single quotes, your string will not be recognized as a template string and the variables will not turned into real actual values.

This works:


`http://${myDomain}${myPath}"?value=${myValue}`

But, this will not:


"http://${myDomain}${myPath}"?value=${myValue}"

Nor will this:


'http://${myDomain}${myPath}"?value=${myValue}'

I picked this one up the hard way after a particularly frustrating debug session wondering why all my unit tests suddenly broke.

Use Curly Brackets, not Parenthesis

The values that you inject in the string must be surrounded by curly brackets, like an object in JavaScript. For some reason my mind wants to use parenthesis, as if calling a function.

This works:


`http://${myDomain}${myPath}"?value=${myValue}`

But, this will fail miserably:


`http://$(myDomain)$(myPath)"?value=$(myValue)`

Despite these two minor roadblocks, I'm finding a lot of value in template strings because the new way of string concatenation is a lot easier to read than the old way.

Learning Redux - Using CombineReducers() - Part 6

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

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

In the previous sample we split up the reducer and manually called our sub reducer functions. Our reducer function was this:


function reducer(state = initialState, action) {
return {
helloUser: helloUser(state.helloUser, action),
goodbyeUser: goodbyeUser(state.goodbyeUser, action)
}
}

Redux provides a short hand to make that happen in the form of a combineReducers() function. Replace the reducer with this:


reducer = Redux.combineReducers({
helloUser,
goodbyeUser
})

Redux will automatically know how to combine these reducers. Try the app again, and you'll find that it works.

Try the app again.

I hope you enjoyed my series on Redux. Be sure to check out the full book series for an in depth explanation of how Redux and Angular can work together.

Learning Redux - Using Multiple Reducer Functions - Part 5

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

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

Review the Reducer

This is the reducer we had in the previous samples:


function reducer(state = initialState, action) {
var newState = Object.assign({}, state)

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

It is functional, but over time as your application grows will become unwieldy. Each aspect of state is better handled separately with it's own actions and state modifications. To do that, we separate a single reducer into multiple reducers.

Split the Reducer

This example expands on the previous example, to show you how to split a single reducer into multiple reducers.

State objects and Reducers can get very complex in a real-world application. What do we do to make them simpler? What we're going to do is create a reducer for each section of the site and then combine them into our one big reducer function.

Let's start by creating a reducer for the hello portion of this app:


function helloUser(state = '', action){
var newState = state;
switch (action.type) {
case 'NAME_MODIFIED':
newState = action.value;
break;
case 'NAME_LEFT':
newState = '';
break;
default:
}
return newState
}

I created a new function named helloUser(). Notice that this function is named the same name as the state property. This is done on purpose, and you'll find out why in the next article. This function has a similar signature to the reducer. It accepts a state and an action. However, it does not accept the full state object. We'll send in the specific value for the helloUser state, which is just one branch of the main state object. This reducer function only focuses on handling its own state, not other states.

The helloUser() reducer only operates on the helloUser state variable. Notice it defaults the newState to an empty string in the command line signature. We might do something more complex if we were using an object or other data type. This reducer has to handle both major actions. If the name is modified, it sets to the new name. If we said goodbye to the user, then the helloUser resets to an empty string.

Create a goodbyeUser() reducer:


function goodbyeUser(state = '', action){
var newState = state;
switch (action.type) {
case 'NAME_LEFT':
newState = action.value;
break;
default:

}
return newState
}

This reducer only needs to operate on the goodbyUser state. As with the helloUser reducer, and as such only needs to respond to the NAME_LEFT action. In that case, it takes the value from the action and sets it to the new state. The NAME_MODIFIED state is ignored here.

Now, create the actual reducer:


function reducer(state = initialState, action) {
return {
helloUser: helloUser(state.helloUser, action),
goodbyeUser: goodbyeUser(state.goodbyeUser, action)
}
}

This automatically returns an object, representing the new state. The helloUser property is given the results of the helloUser() reducer. The goodbyeUser property is given the results of the goodbyeUser() reducer.

Run the app and you'll see it working.

Learning Redux - Define an Initial State - Part 4

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

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

I want to expand on our previous sample to define an initial state. Technically we already do that inside the reducer, like this:


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

But, this can be simplified with some code tweaks. First, define the initial state:


var initialState = {
helloUser : '',
goodbyeUser : ''
}

Now change the reducer method signature:


function reducer(state = initialState, action) {

We're using syntax shorthand to define the default argument if state is undefined. Try to run things again, and the app should work.

In a real-world app, I'd probably create the state as its own class, and pass a new instance of the state into the method as the default argument. Such details are left out in this proof of principle sample.

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.

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.