[MUSIC PLAYING]
Hey, everyone.
What's up?
It's Rob Dodson.
Today on Polycasts, I want to teach you
a very powerful pattern for extending your element
prototypes using behaviors.
Behaviors are going to unlock a totally new world for you.
Also, I want to make sure you all stick around to the end
because we're giving away swag during Q&A time.
We've got things like hoodies, shirts, stickers,
lots of awesome stuff.
So be sure to hang out for that.
All right.
Enough yakking.
Let's dive in.
So what exactly is a behavior?
Well, in a nutshell, a behavior is a little module of code
that you can mix in to your element's prototype,
giving your element's prototype additional properties,
listeners, and even methods.
Now, you may be familiar with doing something similar
using inheritance.
But there are a few issues with inheritance
that behaviors help solve.
For example, let's say you have a menu
and you want it to highlight whichever one of its children
is currently selected.
And because that's a really useful functionality,
you may pull it out and abstract it into a parent element.
Now you can have multiple elements that
inherit from that parent and get that same functionality, which
is great.
But what if you want to also add multi select behavior
to just two of these elements?
You don't want to duplicate the code.
So you could put that up here in the parent.
But that means that this element down here
is going to have to inherit all of that code
even if it doesn't use it.
It's kind of forced to take in all this cruft.
Another issue is multiple inheritance.
So let's say I want to add a cool animation ripple effect
to all of these elements.
It doesn't make sense to put that in this parent
because this parent has one job, which
is dealing with selection.
So I might end up building kind of an inheritance
chain like this, which is sort of a kludgy way of solving
that problem.
This is where behaviors really shine because they
solve both of these issues.
A Polymer element can hold an array of behaviors,
meaning we can mix in as much functionality as we want.
So our menu could have a selectable behavior
to support highlighting in one of its children.
Then it could add in multi select behavior if it needs it.
And finally, it could add in that ripple animation behavior.
Because you can pick and choose the behaviors that
get added to your component, you have
extremely fine grained control of the code
that goes into your element.
And that eliminates cruft, and it also
makes your element easier to reason about.
So now that you understand why behaviors are important,
the next step is to learn how to implement them
in your own components.
Let's check that out.
Behaviors exist as global objects.
So it's important to give them a namespace.
I'm just going to go ahead and create
a namespace called MyBehaviors.
And the behavior I'm actually going to implement
is called PressedBehavior.
And a behavior is going to look just
like the prototype for a Polymer element.
So that means it can have a properties object.
Those properties will be mixed into my elements properties.
So here, I'm going to create a properties object
with a property called pressed.
It's a Boolean that defaults to false,
and it's set to read only.
So I don't want anyone to set this value.
I just want it to change in response to events.
I can also add listener objects to this element,
just like you would with a Polymer element.
I'm going to listen for mousedown and mouseup events.
I'm going to attach those to these two handlers-- addPressed
and removePressed.
I'm also going to a prefix these handlers
with a little underscore.
And that is to signify that these are protected methods.
So they're not public.
I don't want the outside world calling them.
Then I'm going to add the implementation
for these methods.
So I'm just going to add two functions here
for addPressed and removePressed.
And they're just going to add the pressed class
or remove it from the class list.
I can also create abstract methods.
So maybe I don't provide an implementation here,
but the element that uses this behavior
could provide its own implementation.
So I'm going to create two abstract methods, one called
onPressStart and one called onPressEnd.
And I'm going to mark these both as abstract.
So again, no codes going in here.
But someone who uses this behavior can implement
their own version and these will fire
when addPress or removePress happens.
I can even add life cycle callbacks to this behavior.
So I can go up here and add a created callback.
And this is going to be executed after the elements own
life cycle methods have had a chance to run.
So here, I'm just going to log to the console
that an object using this behavior is in the DOM.
Next, I'm going to create a button
element to leverage that behavior that I just wrote.
So I'm going to import the behavior's definition
the same way that I would import the definition
for another Polymer element that it depends on.
Then, down here in its behaviors array,
I can just drop in the name of the behavior that I'm using.
So I'm going to use my namespace here, MyBehaviors.
And the name of the behavior is PressedBehavior.
And now I can add some CSS to take
advantage of that press class.
So up here at the top, I'm going to write a style tag.
And I'm going to use the host selector
to target the pressed class.
And when it is present on this button element,
I want it to run an animation called bounce.
And the bounce animation is just a keyframe animation
that I created right here.
So over in Chrome, I'm going to pop open my DevTools
so you can see what's going on.
I will find the element in the document.
So here it is.
And when I click on it, you'll see that it's going to animate
and that class is going to show up.
When I let go, the class gets removed.
So I click on it, it animates.
The class shows up, and then it disappears.
Now let's try this again with another element.
And this time, I'm going to use one of those abstract methods.
So it's the exact same process as before.
I'm going to import the behavior.
I'm going to add it to this element's behaviors array.
And then, after that's set up, I'm
going to write an implementation of the onPressEnd method.
And I'm just going to have it alert a little message
that I've come up with.
So when that is ready to go, last thing I'm going to do
is add some styles.
So I'm going to add-- again, the host selector here,
which is targeting the press class.
This time, it's going to add a box shadow to the element.
So back over in the document.
Again, pop-up on the DevTools.
You can see I've got my input element here.
When I click on it, it's going to get that box shadow.
The press class is added.
And when I let go, that alert is going to fire.
Also, I can go over to the console
and you can see that the created life cycle callback
that I implemented in the behavior is firing twice
because I have two elements that are each using that behavior.
Now, this behavior that we've been building
is a great starting point but a little contrived
for the sake of this demo.
If you want to see some really powerful behaviors,
go check out the element catalog.
There, you'll find behaviors for doing custom input field
validation as well as behaviors for accessibility.
The iron-a11y-keys-behavior for instance,
adds a key bindings object that lets you map key combinations
to handlers.
It also normalizes key codes across different platforms,
which is really useful.
Finally, you've got the neon animation
set, which heavily uses behaviors
to define animatable elements.
In fact, now that you understand behaviors,
we can start talking about the animation
elements in the next video.
So I hope you found this enlightening.
Behaviors really change the way you
think about adding functionality to your elements,
and they open up a lot of interesting avenues.
That's it for this week, folks.
Be sure to click that little Subscribe button down
at the bottom.
If you have questions for me, leave them
down in the comments.
I do try to read and answer all those if I can.
As always, thank so much for watching,
and I'll see you next time.
Hey, guys.
What's up?
It's Rob.
Q&A time.
Cheo Walker writes in and asks, is there a replacement
for core-list in Polymer 1.0?
So great question, Cheo.
Thank you for sending that in.
I'm actually really happy to announce
that as of very recently, we have just launched
the new iron-list element.
You can follow this link up here to check out the repo.
It's the same core list that you loved before
with all the cool, infinite virtual scrolling goodness,
but ported over to Polymer 1.0.
So lot of really awesome stuff there.
Cheo, thanks for sending in that question.
I'm going to have my minions reach out to you
and send you a swag pack.
If you out there watching-- if you have questions,
leave them for me down in the comments.
I'm going to do my best to respond.
And we just might feature you on the next episode of Polycasts.
So again, thank you all so much for watching,
and I'll see you next time.