Aurelia Code Snippets

I swear this will be my last Aurelia post for a little while. As the community and use of the framework grows, I thought it would be a great idea to create a repository of handy code snippets for use with the Aurelia Javascript framework.

One of those features is the Value Converters feature where a custom Value Converter can be created to modify values within a View. The repository currently has a few converters for working with dates, a couple for iterating objects and eventually there will be many more.

But the repository is not just limited to Value Converters. The repository will have code snippets relating to every aspect of the framework. From custom Router recipes and tricks to custom elements and bindings.

Obviously I don’t want to be the only person submitting snippets, so if you’re keen to contribute: fork the repo and send a PR with your code snippets. The repository for Aurelia Code Snippets can be browsed here.

 

Iterating Objects Using Repeat.for In Aurelia

In Aurelia we already have the power to iterate arrays from within our views and for most purposes, this is fine. However, sometimes there are situations where we might want to iterate an object’s properties or values without needing to normalise it into an array.

In the Aurelia Gitter chat, this question came up, so I decided to create a couple of custom ValueConverters to help with iterating Objects like they were arrays. Other than including the Value Converters themselves, you don’t need to change anything else.

Iterating Object Properties

This first Value Converter will allow us to iterate over an Object’s properties aka its keys.

// A ValueConverter for iterating an Object's properties inside of a repeat.for in Aurelia
export class ObjectKeysValueConverter {
    toView(obj) {
        // Create a temporary array to populate with object keys
        let temp = [];
        
        // A basic for..in loop to get object properties
        // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...in
        for (let prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                temp.push(obj[property]);
            }
        }
        
        return temp;
    }
}

/**
 * Usage
 * Shows how to use the custom ValueConverter to iterate an objects properties
 * aka its keys.
 * 
 * <require from="ObjectKeys"></require>
 * <li repeat.for="prop of myVmObject | objectKeys">${prop}</li>
 */

Using the above embedded Gist, lets iterate a fictional Object we have created in our ViewModel.

export class ViewModel {
    constructor() {
        this.myObj = {
            keyOne: 'myValue1',
            keyTwo: 'myValue2',
            keyThree: 'myValue3',
            keyFour: 'myValue4',
        };
    }
}

Now within our View:
The following is very simple. We will start out by iterating our Object, but we will use our custom ValueConverter to create an Array on the spot with our property values. You could easily do this within your ViewModel without using a Value Converter, but the benefit of this is that we don’t need to add any unnecessary code to our ViewModels.

<template>
<require from="ObjectKeysValueConverter"></require>

<ul>
    <li repeat.for="prop in myObj | objectKeys">${prop}</li>
</ul>
</template>

Iterating Object Values

Lastly, we are going to iterate an Object’s values. Above we iterated an Object’s keys, it is pretty self-explanatory what its values are.

// A ValueConverter for iterating an Object's values inside of a repeat.for in Aurelia
export class ObjectValuesValueConverter {
    toView(obj) {
        // Create a temporary array to populate with object values
        let temp = [];
        
        // A basic for..in loop to get values
        // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of
        for (let val of obj) {
            temp.push(val);
        }
        
        return temp;
    }
}

/**
 * Usage
 * Shows how to use the custom ValueConverter to iterate an objects values
 * 
 * <require from="./ObjectValuesValueConverter"></require>
 * <li repeat.for="val of myVmObject | objectValues">${val}</li>
 */

We are going to re-use the same fictional ViewModel and Object from above to save time. The diffferent being the Object’s values will be displayed, not its properties.

export class ViewModel {
    constructor() {
        this.myObj = {
            keyOne: 'myValue1',
            keyTwo: 'myValue2',
            keyThree: 'myValue3',
            keyFour: 'myValue4',
        };
    }
}

Now within our View:
No explanation is needed, same deal as above. Just watch and learn. As you can see below the only difference is we are using our other Value Converter called, “objectValues” and changing “prop” to “val” in our repeater statement.

<template>
<require from="ObjectValuesValueConverter"></require>

<ul>
    <li repeat.for="val in myObj | objectValues">${val}>
</ul>
</template>

Conclusion

Honestly, that’s it. As you can see ValueConverters allow us to change how data is rendered not only within a normal context, but within things like repeaters. This allows the ViewModel to keep the data standardised and allow the View to dictate how it should be displayed.

If you have any questions or spot any issues with the code, as always, please leave a comment.

 

Aurelia Custom Elements & Custom Callback Events (tutorial)

Before Aurelia came onto the scene I had worked extensively with Angular and then shortly thereafter, React.js (sometimes both together). After using React for a while, I became accustomed to passing functions as callbacks to my components. So naturally when I started using Aurelia and creating custom elements, I tried the callback function approach first.

Callbacks are not the answer

While I was successful in creating a bindable property on my initial custom elements and then passing a function, it became apparent this approach is flawed. Not only do you have scope issues to deal with, but I encountered issues with singletons not being singletons and struggling to pass exact references.

In custom elements we can inject a reference to the custom element’s actual DOM element. What this allows us to do is manipulate the custom element itself and that includes firing custom events that can be listened too when used in your application.

This gives us the benefit of having callback like values, except we listen for events and fire a callback function, not expect the custom element to handle that for us internally.

An example

Recently I published a tutorial on creating a custom Select 2 custom styled select in Aurelia using custom elements. In this tutorial I use custom events to listen for changes on the custom styled select.

If you can’t be bothered wading through the tutorial, I am going to show how to trigger custom events on custom elements in Aurelia. This article from here onwards assumes you understand Aurelia enough to know what a custom element looks like and how Javascript native events sort of work.

I am also going to be using code by my tutorial, so ignore anything specific to jQuery or Select2. We are going to be mostly focusing on events themselves, events which have no 3rd party library dependencies.

The code

custom-element.js
This is the ViewModel for our custom element. This code is taken from my above linked tutorial, hence the references to jQuery and Select2.

// Aurelia Framework specific functionality
// Aurelia Framework specific functionality
import {bindable, inject, customElement} from 'aurelia-framework';

// Import JSPM modules we installed earlier
import $ from 'jquery';
import 'select2';
import 'select2/css/select2.css!'

@customElement('select2') // Define the name of our custom element
@inject(Element) // Inject the instance of this element
export class CustomSelect {
    @bindable name = null; // The name of our custom select
    @bindable selected = false; // The default selected value
    @bindable options = {}; // The label/option values

    constructor(element) {
        this.element = element;
    }

    // Once the Custom Element has its DOM instantiated and ready for binding
    // to happenings within the DOM itself
    attached() {
        $(this.element).find('select')
            .select2()
            .on('change', (event) => {
                let changeEvent;

                if (window.CustomEvent) {
                    changeEvent = new CustomEvent('change', {
                        detail: {
                            value: event.val
                        },
                        bubbles: true
                    });
                } else {
                    changeEvent = document.createEvent('CustomEvent');
                    changeEvent.initCustomEvent('change', true, true, {value: event.val});
                }
                this.element.dispatchEvent(changeEvent);
            });
    }
}

Now lets zero in on the part we are most interested in, the custom event logic.

attached() {
    $(this.element).find('select')
        .select2()
        .on('change', (event) => {
            let changeEvent;

            if (window.CustomEvent) {
                changeEvent = new CustomEvent('change', {
                    detail: {
                        value: event.val
                    },
                    bubbles: true
                });
            } else {
                changeEvent = document.createEvent('CustomEvent');
                changeEvent.initCustomEvent('change', true, true, {value: event.val});
            }
            this.element.dispatchEvent(changeEvent);
        });
}

As you can see, we are creating a variable called changeEvent and then checking what the browser supports. Because CustomEvent is quite new and not supported that well in IE, we check for older support using document.createEvent()

The value of change we can see in the above code is the name of our custom event. For the sake of this example, we are going to keep the event name of “change”. The rest of the logic is pure native events API which you can read up on more here.

The important thing to note here is that setting the property bubbles to boolean of true will help prevent any issues you might encounter, particularly when using shadowDom in your custom elements.

Listening for events on custom elements

As you can see above our Select2 plugin fires off a jQuery change event, then inside we fire off a Javascript event called “change” with a property of “detail” and a sub-value of “value” which is on the event object itself accessible by: event.detail.value.

On our custom element we can subscribe to this event like this: <select2 change.delegate="myEventCallback($event)"></select2>

That’s it. It is that simple. Replace <select2></select2> with your custom element tagName and that’s it. Your custom elements can now fire custom events and you can bind to them on the custom element itself wherever you are using it.

 

Aurelia Custom Element Using Select2 (tutorial)

I know, I just can’t keep quiet about Aurelia. But it is one of the most exciting things to happen to Javascript in a long time. So I decided to write up a quick tutorial on creating a custom element in Aurelia for Select 2, which is a popular library for adding custom select elements to your applications.

Prep

Before we begin, you need to have Aurelia installed locally and the development server running. The easiest way to do this is to download the Aurelia Skeleton Navigation project and follow the README instructions. This tutorial assumes you already have an Aurelia project and that you’re not starting from scratch.

Once you have the Skeleton Navigation project downloaded (or your local project) and all dependencies installed, we need to download Select 2. This can be achieved by opening up a terminal window in your project directory and typing jspm install select2 after the download is finished, the needed changes will be made to the config.js and package.json files.

Now we need to make sure we have jQuery installed as well. This can be achieved by typing in your terminal/PowerShell window: jspm install jquery – okay, now we have everything that we need to continue.

Creating our custom element

In the src directory we want to create a folder called resources and in it create two files: custom-select.js and custom-select.html (One is our ViewModel and the other is the View).

In custom-select.js
Let’s focus on the Javascript part of our custom select first. Open up the file custom-select.js and add in the following:

// Aurelia Framework specific functionality
import {bindable, inject, customElement} from 'aurelia-framework';

// Import JSPM modules we installed earlier
import $ from 'jquery';
import 'select2';
import 'select2/css/select2.css!'

@customElement('select2') // Define the name of our custom element
@inject(Element) // Inject the instance of this element
export class CustomSelect {
    @bindable name = null; // The name of our custom select
    @bindable selected = false; // The default selected value
    @bindable options = {}; // The label/option values

    constructor(element) {
        this.element = element;
    }

    // Once the Custom Element has its DOM instantiated and ready for binding
    // to happenings within the DOM itself
    attached() {
        $(this.element).find('select')
            .select2()
            .on('change', (event) => {
                let changeEvent;

                if (window.CustomEvent) {
                    changeEvent = new CustomEvent('change', {
                        detail: {
                            value: event.val
                        },
                        bubbles: true
                    });
                } else {
                    changeEvent = document.createEvent('CustomEvent');
                    changeEvent.initCustomEvent('change', true, true, {value: event.val});
                }
                this.element.dispatchEvent(changeEvent);
            });
    }
}

We are creating our custom element using a decorator called @customElement() then specifying the tagname. This decorates our class with the require metadata Aurelia needs to know this is our custom element and what the element will look like when referenced in the DOM.

We are also using @bindable which allows us to specify properties of our custom element which are bindable. We are using the default use of @bindable but if you read the documentation, you can go deeper and customise many aspects of how a value is bound (one-way, one-time, two-way), callback functions and more.

More notably you can see we are triggering an event on the element itself (at the bottom of the Javascript file above). When I first started with Aurelia I was passing callback functions, with a parameter called callback however, I encountered far too many issues which was a sign that it was not the right way to go about it.

I have been using React.js since it practically debuted and I became used to the concept of passing callback functions. Triggering events on the element is cleaner and allows us to specify a custom event listener on the element itself when we use it.

In custom-select.html
Now we have our ViewModel above defined, lets create the View. This is the easiest part of our custom element. All we are doing is wrapping a select element in the mandatory <template> tags and adding in some binding values to bind to values passed to the custom select element.

<template>
    <select name.bind="name" value.bind="selected" id.bind="name">
        <option repeat.for="option of options" value.bind="option.value">${option.label}</option>
    </select>
</template>

There isn’t really much to explain here. The <template> tags are a requirement. And anything within is our custom element. We then bind to values specified as @bindable on the custom element itself. These are the values that will be passed through from whereever our custom element is being used.

Using our Custom Element

Now that we have our new custom element. We can either globalise it using aurelia.globalResources() (for another post) or we can require it in our required view. For the sake of simplicity, we are going to focus on manually requiring it in our view and using it.

Now to use our newfound custom element, lets assume we have a ViewModel called test-select.js and an accompanying View called test-select.html we will then provide some options for the custom element, a default selected value and a callback for the change event triggered.

test-select.js

export class TestSelect {
    activate() {
        this.selectOptions = [
            {label: 'My Option', value: 'my-value'},
            {label: 'Some Value', value: '1212'},
            {label: 'Select Me!', value: 'fsdf32423_312'},
        ];

        this.defaultSelected = this.selectOptions[0];
    }

    changeCallback(evt) {
        // The selected value will be printed out to the browser console
        console.log(evt.detail.value);
    }
}

test-select.html

<template>
<require from="resources/custom-select"></require>

<select2 name="myCustomSelect" selected.bind="defaultSelected" options.bind="selectOptions" change.delegate="changeCallback($event)"></select2>
</template>

Conclusion

As you can see, custom elements are nothing more than standard ES2015 classes with a @customElement decorator annotating the class. We can then inject the element instance which we can manipulate, using jQuery we find the input element and then apply the Select2 plugin.

Much like our standard ViewModel’s in Aurelia we might be using elsewhere, we have a view (unless we specify otherwise) which has the same name (unless otherwise specified). This is the beauty of Aurelia, everything is class based and through the use of decorators we can tell Aurelia what said piece of code does within our application.

Hopefully this helps you create some custom elements of your own. I realise I didn’t delve too deep in the specifics of everything we have learned here. Fortunately, the documentation explains everything above and more, so I highly advise you make yourself a tea or coffee and read about custom elements here.

If something doesn’t work, I have made an error you want to ask a question: please drop a comment below and I respond pretty quickly.

 

How To Get An Entire HTMLElement As a String

Recently whilst working on my day-job project I needed to get a HTMLElement from the DOM and then store it as a string. Using innerHTML obviously didn’t make sense because it would only get the inner contents, not the outer. I wanted the whole element.

The logical choice was the lesser known property outerHTML. I say lesser-known because you don’t really see it used all too much, in face of innerHTML anyway. It isn’t the fact developers don’t know about it, it just doesn’t get used a whole lot.

The code

<div id="myElement"><h1>This is my element with content</h1></div>

<script>
var el = document.getElementById('myElement');
var wholeEl = el.outerHTML; // <div id="myElement"><h1>This is my element with content</h1></div>
</script>

As you can see using the outerHTML property allows us to get an entire element and it gets returned as a string which we can store in a variable, transform or send off to a server. The more you know.

 

Unit Testing Aurelia Custom Elements

If you’re a user of Aurelia and you’re writing unit tests, you might have run into some confusion around testing your custom elements, more specifically how you can mock an injected instance of something into a class.

In my case I had a Custom Element which allows me to display a select2 custom select within my application. I was also injecting the Element itself and EventAggregator onto the class using the @inject class decorator.

At the time of writing this, with Aurelia being so new, this kind of information about dependency injection is hard to come by or not really that well explained yet. A few of the concepts in Aurelia are so new to Javascript, that there are not a lot of examples of testing them (especially within Aurelia).

I apologise in advance if this article doesn’t go into too much depth. I am making an assumption that you are already familiar with Aurelia, you have an understanding of decorators and other concepts that Aurelia uses to allow for your apps to be built.

I decided to share this because it took some serious digging through Aurelia’s internals to find out how I can handle injection on a Custom Element class, I couldn’t find any blog posts or documentation on this aspect (that isn’t to say it doesn’t exist, but I couldn’t find it).

For the context of this article, we are going to be working off of the premise of having a custom element class called CustomSelect (supplied below).

src/custom-element.js

import {EventAggregator} from 'aurelia-event-aggregator';
import {bindable, inject, customElement} from 'aurelia-framework';

import $ from 'jquery';
import 'select2';
import 'select2/css/select2.css!'

@customElement('select2')
@inject(Element, EventAggregator)
export class CustomSelect {
    @bindable name = null;
    @bindable selected = false;
    @bindable handler = function() {};
    @bindable options = {};

    constructor(element, eventAggregator) {
        this.element = element;
        this.eventAggregator = eventAggregator;
    }

    attached() {
        $(this.element).find('select').select2({
            minimumResultsForSearch: -1,
            width: '100%'
        }).on('change', (event) => {
            this.changed(event);
        });
    }

    changed(event) {
        var target = event.target;

        this.eventAggregator.publish('select2-'+target.name+'', event);
    }

}

Now lets write our unit test which will take into account the fact we are injecting Element and the EventAggregator for use within our test. We aren’t going for 100% coverage here, but more detailing how we can test custom elements with bindables as well.

test/unit/custom-element.spec.js

// Import our custom element class that we defined earlier
import {CustomSelect} from '../../../src/custom-select';

// Import container and BehaviorInstance for testing
import {Container} from 'aurelia-dependency-injection';
import {BehaviorInstance} from 'aurelia-templating';

describe('the custom select module', () => {
    // References to containers and our element we define later on
    var selectElement;
    var container;

    // Before each test, we set some things up
    beforeEach(() => {
        // Create a global container from the dependency-injection module
        container = new Container().makeGlobal();

        // Register an instance of Element and set it to be a DIV.
        container.registerInstance(Element, '<div>');

        // Using our BehaviorInstance we use the createForUnitTest method and supply our custom element created earlier
        selectElement = BehaviorInstance.createForUnitTest(CustomSelect);

        // You might want to add a class stub here so you can listen to events
        selectElement.EventAggregator = {};
    });

    // A test-case that checks if default properties have been defined
    // this just proves we have an instance and can test bindable values on the class
    // These values are defined as @bindable in our custom element class
    it('contains default properties', () => {
        expect(selectElement.name).toEqual(null);
        expect(selectElement.selected).toEqual(false);
        expect(selectElement.handler).toBeDefined();
        expect(selectElement.options).toEqual({});
    });
});

Conclusion

This is just a taste-tester. I am working on a larger article that will go into detail testing parts of Aurelia like mocking http requests, attributes and other parts of Aurelia that aren’t well documented in the testing department.

 

Copying Your Local SSH Public Key To A Remote Machine/Server In Mac OS

When it comes to working with your servers (or any remote machine for that matter), public key encryption is a must. The basics are: you register a public key on the server-side and then use your private key to authenticate with the remote machine.

So you’ve generated a new SSH keypair or you have your existing SSH keys in the form of id_rsa or whatever. Now you want to push them to your remote server so you can use your private key to login?

cat ~/.ssh/id_rsa.pub | ssh <user>@<hostname> 'cat >> .ssh/authorized_keys && echo "Public key successfully copied"'

You of course will want to replace <user> and <hostname> with their appropriate values and supply any other required values.

You should never copy and paste shell commands off of the internet, so lets quickly explain what the above code does. We actually are calling multiple commands one after the other, rather than one method that does everything for us.

  • cat ~/.ssh/id_rsa.pub — The concatenate command can do many things, but here we are simply concatenating the contents of our public key and then it is returned to the terminal window
  • | — We then pipe the returned contents of our public key file to an ssh call
  • ssh @ — This is where we connect to our remote machine where we want to save the key
  • cat >> .ssh/authorized_keys — Assuming everything went okay, we then use cat command to store the piped contents of our public key into the authorized_keys file
 

Windows 10’s Wifi Sense Feature Is Awesome

How many of your friends and family come over and want to use your wifi? For me, It would take me a while to count all of the people who I have given access to my wifi connection. Usually I just give them the password when they come over or type it in for them without thinking twice.

Of all of the people who have used my wifi connection, they all have the details saved so they can connect later without asking for the password again. This is why I like the Wifi Sense feature in Windows 10 because it mitigates the need to share my wifi password with anyone.

But that hasn’t stopped everyone from decrying that Wifi Sense is a security issue and that your password is being shared with contacts. Everyone is wrong, this feature merely allows you to share wifi access with friends without having to give out your wifi password.

The alternative to Wifi Sense is literally giving out your wifi password (or typing it in for them), of which this wifi password using password extraction applications can be revealed. If anything, Wifi Sense actually adds a layer of security to your home wifi network.

If you have shared access with a contact whom you’re no longer on friendly terms with, just revoke their access and that’s it. They need to be within your range to get the Wifi Sense token to access your network anyway. Revoking access means you can keep using the same wifi password without needing to change it and retype into all of your devices.

While Windows 10 might have some pretty questionable privacy setting defaults and features, Wifi Sense isn’t the security risk everyone is making it out to be.

 

Standalone Bootstrap 3 Grid System

Lets be honest. There are developers who love all of the additional styling for forms, typography and widgets that come with Bootstrap and there are those who absolutely despise everything Bootstrap has and stands for, with exception (for most) the great grid system.

Recently I wanted to use the Bootstrap grid system but without having to use Bootstrap itself. While Bootstrap does offer the ability to customise your download, if you are like me and you use JSPM or Bower for managing stuff like this or you use Git sub-modules, then including just a stylesheet file into your project isn’t the most ideal approach.

Fortunately, someone has done the work for us and created a standalone version of the Bootstrap Grid System. You can read all about the bootstrap-grid package here on NPM. Really there is nothing to it other than a standalone CSS file.

Bower

You can get it from Bower by typing: bower install bootstrap-grid --save

NPM

You can get it from NPM by typing: npm install bootstrap-grid --save

There are plenty of other ways to get just the Bootstrap Grid System, but if you are like me and you always choose the quickest and best solution (no point reinventing the wheel, right?) then the bootstrap-grid package has been helpful to me.

 

Geronimo Jerky (All Flavours) Review

Geronimo Jerky is a small Brisbane based company that produce beef jerky. At the helm is The Big Chief aka Mark Hoyle, who moved to Australia from the USA 20 years ago, bringing with him an authentic native American family recipe for jerky.

Their slogan is, “The best beef jerky you’ve ever tasted” it is a pretty big claim to make, so does Geronimo’s jerky live up to the claim?

I have been buying their jerky for a while now and they occasionally have great sales. Recently they had a 50% off the 40g bags, so I ordered twenty. I got a few of each flavour that they have, some more than others. I thought it would be a great opportunity to review all of their jerky.

I am by no means a jerky expert but when I stayed in the US for a few months working, I took advantage of the opportunity to try as much beef jerky as I could. Understandably jerky is big business in the United States and there are a lot of varieties to choose from. I tried a lot of great jerky, some mediocre, but I sampled what smaller jerky companies could offer.

It is worth mentioning all of Geronimo’s jerky has no preservatives, no colours or anything you can’t find in your own kitchen. The ingredients read like a shopping list, hence the slightly lower shelf life of around 3 months compared to other offerings with a shelf life of double and sometimes triple that of Geronimos.

All jerky flavours also use the original flavoured jerky as the flavour base and add on top of it. As most jerky connoisseurs know, a great jerky base is essential.

One of the only downsides I found to be quite consistent is the jerky is quite hard. It is hardly a deal breaker once you soften up the meat, but those initial bites can be quite hard. I would equate eating a piece of Geronimo Jerky to a nicely flavoured well-done cooked steak.

Geronimo Original Jerky

The original variant of the jerky has this lovely soy taste to it, but it isn’t overly salty. The ingredients list soy beans, so I wonder if perhaps instead of just using soy sauce, they’re doing something else with the soybeans themselves? It would explain the lack of dominating salt taste. The meat has a nice natural flavour and slightly marbled akin to a delicious steak.

Geronimo Pow Wow

The Pow Wow to me had a very similar taste to that of the original. Although I could taste hints of teriyaki sauce and brown sugar, they didn’t dominate the flavour profile of the meat. It was more of an after taste that hits you after a few chews.

The package lists this as a flavour for the kids, but my fiance actually loved this one and I thought it was delicious as well. I found Pow Wow to be the most binge-eat worthy jerky because it has no heat and it makes your mouth water when you chew it.

Geronimo Spicy Sharman

Even though the name might confuse some, this isn’t a hot jerky at all. People often confuse spicy with hot, this is a subtly sweet jerky that is super delicious and has hints of ginger and the curry gives it a distinctive spicy taste that makes this one easily one of Geronimo’s most tasty jerkies.

Geronimo Stampede

This is an interesting jerky. To me it tastes like the original, but has a few subtle spice notes in it. The most interesting ingredient in this is the inclusion of Guarana which is added in during the marinating phase.

This is the first jerky to use Guarana as an ingredient and while I can’t say for sure if it made me feel more alert, the concept of an energy jerky is pretty interesting nonetheless.

I think the Guarana is more of a gimmick than anything. If I want a pick-me-up, a large coffee is considerably cheaper and probably more effective.

Geronimo Buckshot

Geronimo’s Buckshot jerky is easily my favourite variant of their jerky. It is basically the original jerky with heavy hints of peppercorn, you can actually see the pepper if you look in the bag.

Absolutely delicious and hard to not binge eat. There is nothing complicated here, just the right amount of pepper and the delicious jerky base.

Geronimo Sidewinder

The Sidewinder jerky has a slightly bit of heat to it. If you can’t handle a bit of heat courtesy of the Chocolate Habanero chilli which comes in between 425,000 – 577,000 Scoville heat units, then you might want to avoid this one. Although in its defence, it isn’t as hot as you would think.

The package does however say “it’s not too hot” but this would be out of the comfort zone for many. I found the heat of Sidewinder to not be overly consistent, some pieces were barely hot and some pieces were very hot.

The Sidewinder has a very unique taste, a slight sweetness which comes from the Habanero Chilli which has a slight passion fruit flavour and subtle hints of capsicum.

Geronimo Blazin’ Saddle

From my understanding Blazin’ Saddle is supposed to be the second hottest jerky that Geronimo produce, but I honestly found my bags of Sidewinder were consistently hotter than Blazin’ Saddle.

Perhaps it was just the batch that I received, but my Blazin’ Saddle (even though the ingredients had a few hot ingredients) wasn’t overly hot.

The lack of heat was a bit disappointing, but it was still delicious though. The lack of sweetness because of different chillies being used is a nice change from the Sidewinder.

Geronimo Flamin’ Arrow

This is Geronimo’s hottest jerky and unlike Blazin’ Saddle, this one lives up to its tagline of being their hottest jerky. The heat is considerably hotter than that of any of Geronimo’s other jerkies, I found it a little hard to pinpoint certain ingredients in this one. Make no mistake this is a delicious jerky.

But be careful, they’re not exaggerating when they say this is hot. Seriously, wash your hands after eating this. If you touch your eyes or nose, you’ll be in a world of pain temporarily as it is like rubbing chilli in your eyes (don’t ask me how I know this).

Flamin’ Arrow is not a binge jerky. I recommend you eat this one in moderation or you’ll experience first hand what Johnny Cash was really singing about.

Conclusion

So, does Geronimo Jerky back up the claim of “The best beef jerky you’ve ever tasted”? Absolutely. Even though at times I did find the jerky was a bit too hard to chew, this is just because I have sensitive teeth. Geronimo Jerky is perfect and much better than anything I have tasted from any other Australian jerky producer.

Properly cooked jerky is supposed to crack when you bend it, not break. Geronimo’s jerky consistently cracked when I bent pieces randomly from the whole flavour range.

Combined with the excellent range of flavours and balanced ingredient ratios, you can see why Geronimo win the awards they do and are making waves in the jerky community in Australia and abroad.

The things I would do to get my hands on the Geronimo jerky base. Go and buy some Geronimo Jerky now and thank me later.