Hey, everyone.
What's up?
It's Rob Dodson.
Today on Polycast I'm going to take you
down the path of creating a public API for your elements.
We're also going to be answering questions from the audience,
so be sure to stick around for that.
First, let's hop into some code.
So the first part of creating a public API for your element
is declaring public properties, and this
has changed a bunch from Polymer 0.5 to the newest version.
In previous versions of Polymer, if you
wanted to declare public properties for your element
there was an attributes attribute that you
could put properties in.
There was a published object then
you could put properties in, and sometimes it was confusing.
You know, where should you put your stuff?
So in the latest version of Polymer,
this has all been consolidated into one single properties
object, and it's a very powerful object.
So let me show it to you, and we can check out
some of the cool things that it does.
So first and foremost, I've got an x-custom element
that I've created here, I've got a properties object,
and I've got two properties, first and last,
and I've set string to their values.
Which basically tells Polymer that when someone passes
in a value for first and last, that value should
be de-serialized to a string.
So that's really nice.
You can de-serialize to various other types,
like number, object, et cetera.
Another cool thing that you can do
is you can pass in a default value for a property.
So I've got an age property here,
I've set its type to number, and a default value of 42.
You can also create observers for your properties.
So these are functions that will run
whenever the property changes.
So here I've set observer to this age changed function.
And in previous versions of Polymer,
we had this notion of changed watchers, which were functions
that we kind of secretly implemented for you.
If you had a public property, you've
got one of those functions for free.
It was a little bit of magic.
Now that has been sort of removed,
and if you want to observe a changing
need to explicitly create an observer like this.
Which is nice.
It sort of-- if someone was looking at your code
and they weren't quite sure where
that function was coming from, this
clears up any confusion there.
And one thing to point out is that because this
is effectively like a private function,
I don't want a bunch of people calling this method,
I would only like it to run if my property changes,
I'm prefixing it with an underscore.
And that's something that we're doing with all the Polymer
elements just to highlight to folks that this
is internal to the element and not meant to the outside world
to call.
And other thing that you can do is
you can have your element dispatch change events anytime
its property is updated.
So this is similar to the way that native Dom elements work.
You've got input, and select, and, you know,
when they change they actually fire events every single time
to notify folks.
So adding a notify property to your element
is going to dispatch those change events for you.
So I'll get an age changed event.
And the nice thing is this is actually
the basis for the two way binding system in Polymer.
So if you want one of these properties here to a bindable,
you need to make sure that you've
got notify true set on it.
Also, hopefully, this makes it easier
to interop with other frameworks.
So there are other frameworks out there
that have their own data binding systems,
and previously it was unclear how
they could know at what point in a Polymer elements life
to actually check for changes.
This way it's getting an event, it
can listen for that it's consistent,
and that way we can, hopefully, interop with some other data
binding systems.
Now, another really awesome that you can do
is create computer properties.
So let's say I want to take first and last
and combine them together into one value.
I can do that here by passing a computed key, and then
a compute full name function name,
and I'm passing in the two properties
that I would like to send in as arguments.
So I'm passing in first and last.
Now, it's important to include these arguments here,
because what they do is they tell Polymer
that any time first or last changes this compute full name
function should run again to update this value.
So very, very useful trick there.
Another thing that you can do is create read only properties.
So let's say you have an element with some internal state,
you don't want the outside world playing around with it,
you can set that property to read
only so that way folks can only get the value,
they can never set it.
Lastly, one thing that's really cool
is you can reflect values back to attributes if you need to.
So this is really helpful if someone
is trying to style your element with the CSS attribute
selector.
You probably won't use this guy that much,
but it's there if you need it.
For the new properties object gives you
a kind of power, let's hop into the Code Editor
and actually put this into practice.
So I'm going to start, as I do with all my elements,
in a Bower JSON file.
I've got an element that I've created called name tag,
and in my dependencies I've listed Polymer 0.9.0-rc.1.
So this is the release candidate for rc.1,
which is what's currently available at the time
of this recording.
But if you're watching this and, I'm assuming by now
the 0.9.0 tag is actually out-- so you can actually
take this value here and probably
just go ahead and replace it in your Bower JSON
with a little caret 0.9.0.
And that should get you the latest tag of Polymer.
Now over in my terminal, I'm going
to run Bower install to pull down that version of Polymer,
and then back in Sublime I can create
a name dash tag HTML file.
And this is where I'm going to put my elements definition.
The first thing I've got to do, as always,
is use the canonical path to import Polymer.
Then I'm going to create a Dom module was
an ID that matches my elements tag name, so ID of name tag,
and inside of there I will throw a template
and that's where I'm going to put all of the local Dom
content for my element.
The next thing I need to do is call the Polymer constructor,
and I need to give it an is property
and pass in my tag name.
And then I'm also going to create a properties object
for it, and I will create first and last properties
and I'm going to set those to strings.
Then I will create a div up here called full name,
and I will bind those values up to spans inside of that div.
Now in previous versions of Polymer,
you could actually create these binding expressions
where you have multiple values and multiple bindings
all kind of mushed into one tag.
Currently in Polymer, that is not
supported though it is on the roadmap.
So if you need to get both first and last into this div,
you've got to wrap them inside of spans which
is a little funky and we're going to come back
to this point in a moment.
But so far, just with this right here,
we're ready to preview our element.
So I'll go to my index file, and I'm
going to import definition for my name tag element.
And then down in the body, I can drop in a name tag
and I can configure it with first and last value.
So I'm just going to pass in my name as those values.
Next, I'm going to run the trustee polyserve module
to actually preview my element.
Polyserve is a little local node server
that you can use to test out your component,
it plays very nicely with Bower.
If you have no idea what I'm talking about,
you can check out this video her right here.
We've got a full episode which explains how to get up
and running with polyserve.
If you are building a lot of elements,
this is an invaluable tool.
So it is worth your time to check out that episode.
Now, over in Chrome, I'm going to refresh the page
and you can see over here-- I'll kind of
boost this up a little bit for you--
that my name is now showing up.
So I've got first and last, those binding values
are being displayed there.
It's a little boring, right?
But at least you can see it works.
And back in my element definition,
I'm going to try to clean this up a little
bit because having those spans there
is little bit of a funky hack, and to do that I'm going
to use a computed property.
So in my properties object, I will create a full name
property.
I'm going to say it's computed, and then it
computes first and last.
And then down here, I can actually implement that method.
So it takes first and last as arguments,
it returns a string that is the concatenated values.
Then up in my div, I can just drop
in a binding for full name.
Now the next thing I want to do to make
this tag look a little bit nicer is actually add
some styles in here.
So I'm styling the host, and I'm styling that full name div.
And what this is going to give me,
when I go back to Chrome and refresh the page,
is something that looks a little bit more like a name badge.
And you can see that I still see my full name their
using that computer property.
OK, I'm going to clue you in on a little pro tip now.
If you'd like to declare your computer properties in line
you can totally do that, and that's really useful
if you want to have a computer property maybe only
in one place.
It'll keep your properties object nice and tidy, so
let me show you how to do that.
So to declare a computed property in the line,
we can actually delete this full name property
that we've got here.
And then up in our binding we can just
call compute full name, pass in first and last properties,
and then that's going to call this guy and return a value.
So going back to Chrome, refresh the page,
I see the exact same thing, but I've tidied up my properties
object a little bit.
And this, again, is helpful if you have a property that maybe
you're only using in one place.
Now one last thing I want to show you
is how to add a public method to your component.
So what I'm going to do is I'm going
to add like a shake method so that the name tag actually
wiggles around a little bit.
So to do that I'm going to start off with a little bit of CSS,
and notice this host selector that I've written here.
So I'm targeting the host and then I've
got these parentheses, and I'm passing in a class name.
And what that does is it allows the element
to reference itself.
It's basically saying if I have a class called
shake applied to me, then use all of these styles.
I'm just creating an animation here.
What I'm going to do is drop in some key frames,
and these key frames just have the element
go to the right a little, to the left a little,
and then back to the center.
And I've got the vendor prefixed versions of this key frames
as well, so, you know, moz key frame,
webkit key frame, et cetera.
So it looks like a lot more code than it really is.
Now I'm going to go down to my prototype,
and I can actually implement a shake method.
So all I'm doing is I'm saying this this.classlist.toggle that
shake class.
So you're going to add it, the element
is going to shake around, you're going
to toggle it so it'll removed, called again,
the element shakes around, et cetera.
So we hop over to Chrome, and I can pop up in the dev tools
and use this little inspector here
to select my element in the document.
And you can see that I've got highlighted there,
and I can hit Escape to open up my console,
and I'll show you a neat trick if you haven't seen it before.
When you're in the console and you've
got an element selected up there,
you can hit $0 to actually select that element.
It's like calling query selector.
So now I can just say $0, call that shake public method,
and you'll see it shaking.
I can call it again, and you'll see
that that class that we added gets removed because we're
calling classless toggle.
Called again, it shakes.
Call again, class gets removed.
So on and so on.
So a bit of a quick and dirty example,
but now you know how to add public properties
and public methods to your element.
So there you have it.
You now know how to create the public API for your element.
Now don't run away just yet, stick around
because in Q&A time, we're going to be
answering questions in the audience
and giving away some swag.
Be sure to click that little subscribe button.
As always, thank you so much for watching,
and I'll see you next time.
All right, folks.
Q&A time.
Today's question comes from Kash Cummings who asks,
you've mentioned using the [INAUDIBLE]
before to style elements can be dangerous because it can
cause unintended side effects.
Is there a more general way to style
elements that doesn't require knowing
all about their internals?
It's a really great question, Kash, thanks
for sending that in.
This is actually one of the cooler features of the latest
version of Polymer.
We've got a brand new styling system,
it's still experimental but has shipped.
You can follow this link right here to read more about it.
It is based on CSS variables and custom properties.
And I personally think it's so cool.
The next episode of Polycast is actually
going to be all about it, so stay tuned for that.
Again, thank you Kash for sending in your question.
To all of you out there, please send more questions
down in the comments.
We'll send you some swag if you get featured.
As always, thanks for watching.
I'll see you next time.