Join egghead, unlock knowledge.

Want more egghead?

This lesson is for members. Join us? Get access to all 3,000+ tutorials + a community with expert developers around the world.

Unlock This Lesson
Become a member
to unlock all features

    Design Patterns: Mixin

    Brett CassetteBrett Cassette

    AngularJS supports "mixins" with angular.extend, but this approach has some drawbacks. In this video Brett takes a look at a more robust approach to mixins inspired by the Ruby programming language.



    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson


    Brett Shollenberger: Hey guys. Today we're going to talk about mixin pattern in AngularJS. The mixin pattern is really common in a lot of different languages. What it's going to allow us to do is to factor out reusable code that we want to include in a lot of different objects or classes or whatever into a single module so that we can reuse that module everywhere.

    Kind of what we have defined here is just this mix into factory that we're not actually mixing into yet. We've just defined this cool true property. Over here, we're checking that cool does, in fact, equal true. We see here that it does.

    But let's assume that we want to factor this out because we want to use this everywhere. We want everyone to know that cool is true. That makes sense, right guys?

    What we can do here now that we've defined this mixin is to actually go ahead and inject it. Then Angular gives us this syntax called angular.extend. This takes something to mix into, which is this mix into object and something to mix in, which is this object down here. This is going to copy all the properties from this object to this object, so even if we get rid of this, this still works.

    But what's not actually going to be expected for us is if we try to override this by saying cool is false. In a lot of other languages, we would expect that to be true. But that's not so in this case.

    What we actually want to do here is have the mixin be kind of like a pseudo parent class. It's not actually going to be a parent of this object, but it's going to kind of inject itself into the hierarchy there like it would in other languages.

    The way that we do that is by actually using a bower component that I've made for us here called Pocketknife. This provides us with this PK mixin functionality. The difference is that if the receiving object doesn't have a property already by the given name, then it'll override it. Again, this isn't really injecting itself into the hierarchy, but it's just kind of simulating what that would do.

    Now, if instead of angular.extend, we said, pk.mixin, this will work the way that we expect it to. What's even more is PK mixin gives us a lot of fine grain control over the way that we define how our properties get mixed in. It does that through this object.define property syntax that's given to us by JavaScript.

    What this actually lets us do is save things like whether or not we can enumerate over that property in the object and what the value of the property is, or we can define a getter function and the setter function. All kinds of stuff that we may want to do.

    Just to show you really what that's capable of, what I'm going to do is copy this enumerable functionality out of Pocketknife that I've already defined for us. This is very similar to Ruby's implementation of the enumerable module that gives many different objects like arrays and hash tables the ability to be enumerated over. We're going to inject in enumerable.

    What that's going to do is allow us to, on our array prototype actually mixin this enumerable functionality. We can see that if we comment that out first and we were to test things like 123.collect and we pass it a function of the number. We want to return that number plus 1. We would expect, if 123 had 1 added to each of those, it would be 234. We're going to get this object, array has no method collect error.

    What we're going to actually do is uncomment this. We're going to mixin these enumerable functions from enumerable into the array prototype. Now we get this spec passing.

    Just to kind of show you what we had access to, let's just kind of get rid of some of the rest of these. We need to have the each method still, and we need to have collect, because collect uses the each method.

    But if we set enumerable to true here, all of a sudden, not only do we have 2, 3 and 4, but we also have the collect function as a property in our array, or an item in our array. The reason is because enumerable gives us control over whether or not that object can be iterated over. Again, if we set it to false, now things work the way that we expect them to.

    Really, what Pocketknife is giving you access to is this kind of fine grained control where you can say exactly how you're defining the properties on your mixin object. If I were to give one piece of advice to look into after the screencast, it would be all the options that you have here on this object.define property method in JavaScript.

    That's how I'd recommend creating your mixins, guys. Happy mixing in.