What do you want to learn?
Leverged
jhuang@tampa.cgsinc.com
Skip to main content
Pluralsight uses cookies.Learn more about your privacy
Building a Web Application with Polymer.js and Material Design
by Bill Stavroulakis
This course will introduce Polymer’s basic functionality by building together a real-life administration dashboard.
Resume CourseBookmarkAdd to Channel
Table of contents
Description
Transcript
Exercise files
Discussion
Learning Check
Recommended
Introduction
Introduction
Hi, this is Bill Stavroulakis and welcome to this course on Building a Web Application with Polymer.js and Material Design. We are hired. Let's imagine that an educational institution hired us to create a dashboard for their school. They want a simple authentication where they can log in, preview some data for their school, change the profile information, and view/edit their staff information. A simple chat is also necessary for them to chat with each other. They would like a fully responsive, single page, real time web application that can be extensible with any backend technology such as Node.js, C#, PHP, or Ruby, as they haven't decided yet. Time for us to create a simple, strong, extensible, and easy editable mockup to convince them that we are on the right track. We can select the wide range of front-end technologies such AngularJS, EmberJS, Backbone.JS and UI libraries such as Bootstrap.js, however, we will select Polymer.js and Material Design for the job and see where it will take us. By creating this application together, you will understand in action the fundamentals of web components, material design and the Polymer.js framework.
Our Application
Let us view the end result of our application. At the end of this course you'll fully understand how to create this application with the use of Polymer.js. First of all, let's preview the login page. As you reenter the username and the password and click on enter, we have successfully logged in the home page. In the home page you can preview some blocks of data and a welcome message. On the left there is a menu with our pages and on the right there is a drawer with our friends. We can either pin or unpin our drawers or open and close them. We can click on the profile link and preview or edit our profile. Also there is a staff page where we can search, add, edit, and delete staff members in our application. If we click on a user on the right, we can chat with them. Let me open two tabs so you can see that this is real time as well. So once we send a message on one page, it automatically updates on the other. Finally you can also notice that our application is fully responsive as well. As we decrease the width of our application, you can observer that the drawers unpin automatically to create some space and sorting our blocks accordingly. So it is time to dive in and create this application together with Polymer.
Who This Course Is For
Working Example - Structure
Introduction
Hi. This is Bill Stavroulakis and welcome to the second module of this course on building a web application with Polymer.js and Material Design. In this module we'll create the basic shell of our application. We'll begin setting up our environment and we'll create a simple drawer system. While implementing these sections, we'll go over together the basics of Polymer.js.
Setting Up
Okay, I know that the hardest part of an application is the beginning. There are so many parts that you have to juggle at the same time. That is why usually we use starter kits or Bootstrap packages that give us a nice wrapper and starting point to work with. For Polymer, you can check out the Polymer Starter Kit which offers a nice base to begin with; however, I would like us to create this application from the beginning so we can set up each layer together, learning concepts and strategies at the same time. You can preview a big part of the project at the link below as it is a part of the Polymer Dashboard project. It is open source and on GitHub so don't hesitate to fork it and contribute any changes or fixes.
Installations
A good starting point would be to create a shell or skeleton of our application. Let us see what sort of technologies we'll need to set up our basic application. I'm using Windows 10 and we'll work on Visual Studio Code as my text editor. You can use any HTML/CSS/JS editor you like such as WebStorm or Sublime. For rapid prototyping I'll be using NodeJS as a very simple backend for our application since we will focus mostly on the front end side. To run NodeJS and other technologies that we'll use such as _____, you have to download NodeJS from Node.js.org and the Git Bash for Windows so you can run the commands necessary from msysgit.github.io. Everything seems ready. Let us create a folder where we'll add all of the files of our application. We'll open Git Bash and navigate to that folder. To keep my paths nice and short, I'll use the d drive and create a folder with the name polymer-project. Now it's time to set up our project.
The Application Shell
Time to open Visual Studio Code so we can write some code. After installing Visual Studio Code you can double click on the shortcut on your desktop to open the application. Then we'll click on file, open folder, and find the folder we created in the previous video to load our project. We'll create two folders; the app folder which will include our application and the demo server folder which will include our NodeJS code. Also, let us create a package.json file for our node model settings. The first file we'll create in our app is index.html which will run as our default page. We'll add some boilerplate HTML code and the text test in the body tag. In our package.json file we'll add the following settings which will declare the Node modules needed for our application. For now we will need the Express module to run our web application. In our app.js file we include the Express module, initialize it, and include the path module. For our default path we'll serve the index.html file and set up the http module to listen to the 8080 port. From the Git Bash command line we will open the demo server folder, run npm install to install the Node dependencies, and run node app js to listen to our port and serve the index.html file. Let us run local host 8080, now on our browser so we can see the test text and our boilerplate html.
Our First Element
We have everything set up to create our first elements. In our app folder, let's create a folder named components that will store our custom elements and add a new folder named pd-dashboard and a file named pd-dashboard.html. By adding bower.json in our top folder we can include third party JavaScript libraries as well. For now, let us add the Polymer framework. Running bower install in Git Bash we can preview a new folder named bower_components and in that we can preview two new folders which are Polymer and webcomponentsjs. It is time to create our first custom element; however, what is a custom element? Everybody knows and has used the HTML5 elements one way or another. For example, let us add the select element on our page. We can even include some option elements in that select element. As the select element is the fault element, our browser automatically renders it the way expected. We can preview a nice dropdown with the options added. Also, as a special feature, if we add the selected attribute on an option, we can preview that the option is preselected. This select element has attributes such as id, name, which are universal, or some special properties such as selected index to return the index of the select option. Wouldn't it be cool if we could declare our own elements with Polymer, include them on our page, and re-use them? I'm glad you asked because that's exactly what we're going to do right now. In our pddashboard.html file, we'll add the following lines of code. The dom-module element is needed to declare the element so we're using a custom element by Polymer to declare our own custom element. How weird is that? Then, whatever is located in the template tag will be used as the content of our element. On the bottom of the html file we'll add a script tag where we'll add the element in the Polymer scope, which will parse the dom-module. So we declared our element. Time to include it in our page. As mentioned previously, the select element is automatically rendered on all browsers since it's one of the default HTML5 elements. To include our element declaration we'll have to use the link tag, just as CSS but with the rel import attribute and instead of a CSS file, our html file also. Some browsers in older versions don't support the rel import attribute yet, as well as basic web component standards, so we can include the webcomponents-lite library which will work as a polyfill. Everything looks ready for us to add our pd-dashboard element. Let us add it twice and see what happens. Before we launch our app we have to include Polymer as well in our element and add static files in our app js so we can serve static files as well. After running our app on our console and refreshing our page, viola! We can preview our elements data and if we view our pages source we can see the rendered html.
Anatomy of an Element - Properties
In this video we'll see how properties and binding work with polymer. I will create a new folder named pd-drawer and add to files, pd-drawer.html and pd-drawer.css. In the pd-drawer.html let us add an empty dom-drawer tag for now and an empty JavaScript declaration. Our element is ready. Let us add some soul to it and see how properties work. If you've ever worked with Angular, NOCOUNT or any other library that handles data binding, you know how powerful this feature is, concerning HTML, JavaScript data manipulation. Our pd-drawer elements will contain two drawers, a left drawer and a right drawer. These drawers will have two states, show or hide. I'll add two properties under the properties property with the name leftShow and rightShow. The next step will be to declare the type of each property and the value. In our template we'll add two input tags with the value of the properties declared. With the use of curly braces we can connect the values in the HTML with the property in JavaScript. Now let us reference our newly created element in pd-dashboard and add that element in our page. After refreshing our page, you can notice the value of each property displaying in our HTML. That looks great. Let us see what happens once we change the value in the input tag. Hmmm. We notice that it doesn't change below as we would expect. So we have only one-way binding, meaning that the data went from our script to HTML, but once we change the value in HTML it didn't refresh the value in JavaScript. To prove this we'll open the debugger and select our element. With the $0 sign in the console panel, you can see that we can quickly reference the element that was selected by the inspector. So let us see what is the leftShow value in JavaScript? It is true, although we changed it to false in our HTML. Once we change the JavaScript property to false you can see everything refreshing on our HTML. The same happens with the rightShow as well. The conclusion that we reach is that by default in Polymer our properties are bound from JavaScript to HTML, but from HTML to JavaScript. Time to see what different types of bindings exist in Polymer and what sort of combinations we can have. The first finding example is the one we previewed together. I've also included the input change event needed for the input native element in Polymer. In the second binding example, we've added the notify:true value in our property. Now we've enabled two-way data binding so every time we change the value in HTML, it propagates to JavaScript as well. Let us preview this example. We can see the value being true and once we change it to false, the changes are propagated back to the JavaScript property and to any other elements as well from there on. In our third binding example, instead of curly brackets, we'll use square brackets. When we use square brackets, we have only one-way binding again, so either we add the notify:true value or not, the changes won't propagate from HTML to JavaScript, just like the first example. In our fourth binding example, we'll use the readOnly:true value that strongly declares that we have JavaScript to HTML binding only when the element is loaded and after that there is no binding. When I go back to my code and add this value and refresh my page, the changes are applied. Once I change the values in JavaScript the changes are not reflected to the HTML dom.
Anatomy of an Element - Computed Properties
In the pd-drawer element declaration I've added numerous new properties that we will be using throughout our application. Sometimes in our code we need a bit more complicated properties that are a combination of others. In this element we'll need a property that will return the main classes or our element concerning various states. This class is named mainClasses property and we can see it as a string and it is in the computed property. We'll add the method we want to return the value of the mainClasses property. Also, the values that are entered in the method are important because once one of those changes then Polymer will rerun the method and refresh the value of the property. I'll create the method to return the classes and add the property as a class attribute in the drawer elements. So now, once we refresh the page, we can preview the classes, depending on the various states our drawer is in.
Anatomy of an Element - Tap Events
In the previous video we included numerous new properties needed in the JavaScript section of our elements declaration. Now in this video I added some HTML in the template section of our element. This HTML is for the drawer of our site and consists of the toolbar, the left and right drawer, and the main section of our site. To copy and paste this code, you can review the code demos of this module. We will explain more and more the sections of the code added in future videos. Our drawers wouldn't be complete if we couldn't close them or open them at will. I've added some more HTML that contains each drawer section and the main section. Now in each drawer, let us add buttons that will pin and lock our drawers and some buttons that will show or hide our drawers. If we visit the polymer-project.org site, click on guidelines, events, and scroll a bit, you can see how a very simple event works. So on our element we'll add a non-click attribute and create the method to handle that event. For our toggleLeft action we'll lock the left drawer and on the pinLeft we'll pin the left drawer and add the corresponding code for the right drawer as well.
Anatomy of an Element - Insertion Points
In this video we'll go over the very interesting concept of insertion points. As mentioned, components are created so we can reuse them. How can I make the pd-drawer not contain any of my application logic but still use it and reuse it when needed? By now, the way we have created the pd-drawer element, we can reuse it in any of our applications. We just have a chunk of HTML that is the header, a main section, and two drawers. In each of our applications, the content in the header, drawer, and main section will be different. Going back to our pd-dashboard, I'll add some HTML in the pd-drawer. This is our application level code that we want to insert in the pd-drawer element, so we'll have the logo, left menu, right menu, and main section HTML. After returning to our pd-drawer element, I'll add the insertion points with the special content tag. Each content tag has a select attribute that works as a selector to translate our selector. This says, if in the element, when declared you find another element with a class logo, render it over here; the same for the left drawer and the right drawer. We'll refresh our page and see our drawer and the HTML specified in the pd-dashboard inserted in a way in the sections specified.
Summary
If you're still here, then I salute you. This probably is the end of the hardest module of this course, since it was the first touch with numerous new concepts and ways of thinking. We basically created the main structure of our site while introducing the basic concepts of Polymer.js. In the next module we'll try to style what we just created and learn about theming, coloring, and material design.
Working Example - Styling
Overview
In this module we'll talk about CSS and our elements. We'll also dress our site by creating a theme, colors, and seeing what is Material Design and how can we use its principles in our dashboard?
Anatomy of an Element - CSS
Our pd-drawer works fine, but life is not pretty without CSS. We'll open pd-drawer.css and add some CSS in our file and save. In the pd-drawer.html you can see the dom-module element that contains the html of our elements. In it we can include a link tag with a CSS reference. The CSS included in the dom-module will have as scope only the html in the elements and won't be global. So any CSS styles we include will style the html in this section only. How can this be done? If we preview the end results, you can notice that Polymer is adding the style element of that element in the head and if we expand that, you can see that it has wrapped each declaration with that element's name. If we added the link before the dom-module element, the scope would be global.
Theming
Time to create a very nice theme for our page. A theme consists of a collection of rules for our site including the font, basic CSS principles, padding, positioning, and colors. I'll create a CSS folder and add four SCSS files. SCSS files stand for Sass files. Well what is Sass? Sass is a CSS pre-processor. Let us visit sass-lang.com for more info. I'll click on Learn Sass and scroll a bit. With Sass we can use variables in our SCSS files which we'll then compile in CSS, replacing the variables with the corresponding values. We can also nest selectors, import external rules, and combine files. Create mixings and reuse blocks of code. Extend rules. Or even use operators. In my vars.scss file I'll add some basic parameters used throughout my pages. In my position.scss, I'll add some basic padding, margin classes, and other basing positioning classes, after importing my vars file. In my main.scss let us include some CSS for our html. And lastly, in the font.scss I'll declare some font sizing for my headers. Now I'll add these basic principles in my pd-dashboard element. For our SCSS files to compile to CSS files, we'll create some Gulp tasks. In our package.json file we'll add the Gulp, gulp-sass and gulp-insert packages. After running npm install to install our new packages, we'll create a file named gulpfile.js. In the gulpfile.js we can include some Gulp tasks written in JavaScript. So we'll include gulp and gulp-sass and add one task. This task will compile the SCSS files to pure CSS code. We'll open Git Bash and run Gulp to run this task. After refreshing the page, we can see our theme principles in action. Our page, however, still needs some color. Time to create some skins and rules for that.
Coloring
A web page without color is like a programmer without coffee. Well, not exactly, but you get my point. We need color rules. My first step will be to create a folder named skins in the CSS folder and add one skin for now name default. I'll also create two template files called color-vars-templates.scss and skin-template.scss. These two files will contain CSS rules with values, different variables. Now in the default folder we'll add a vars.scss file for our color variables. Let me add some values in there. In my template.scss files, I'll add my color variables. In the template files we'll include the CSS rules as mentioned previously. We'll include these template files in our skins to load them with the variables and colors of the skin, but the rules will be the same. You can check out this CSS code in the demo files, and in each skin we'll create our files, that first include the variables of that skin and then the generic template. We'll open package.json and add some new Node modules. Then in gulpfile.js we will initialize the modules, add a new Sass task to compile the skins as well, create a copy task to copy the colorVars body.css file to the colorVars.css file. Create an insert task to append the style tag in the colorVars.css file. And add a default task that will run a sequence of tasks. It will first run the Sass, then the copy task, and finally the insert task. Now if we run npm install on Git Bash to install the modules and run Gulp on Git Bash, it will run the sequence of tasks located in the default task. In the CSS file created, you can see the CSS rules with the corresponding variables. In the color.css file we have our standard CSS rules that color our elements and classes. Lastly, in colorVars.css you can preview the tag that was appended through the Gulp insert task. Time to include our skins in our application. I'll include these CSS files with Polymer's special link tag. By now, you should be okay with the colors.css class; however, you may be a bit curious on what the colorVars.css file is all about, and why did we include it in the page with the rel import attribute and not with the rel style sheet attribute? If you visit the link below, you'll notice a very cool new CSS 3 feature which are CSS's variables. Polymer implements this technology seamlessly in its framework. Let us review an example. I'll open Git Bash and run node demo-server/app.js to load my site. After refreshing the site, we can see the colors loading properly. Returning to pd-drawer, let us create a new div in our main section with the class main site. Then we'll add the background color for that section and as a background color, we'll use the primary-color- dark variable declared in the colorVars.css file. After refreshing the page we can see that the section defined has the primary dark color. So as you're defining a variable, importing it with the rel import tag, we can use those variables in our elements. Polymer uses certain variables in all of its elements. This would be a good time to include in bower.json all of the elements that we'll be using in our project and run bower install to install them. For example, if we open the paper-icon-button element, you can see that it is applying the primary-text-color variable. If we visit materialpalette.com and select two colors, click on downloads and Polymer, you can see a collection of variables depending on the colors we selected. If we were to import these parameters in our pd-dashboard element, then any element in the pd-dashboard would implement the color palette selected with the variable specified.
CSS Scope
This would be a good time to talk about the scope of CSS in our elements. In our pd-drawer I'll add some custom CSS and I'll split the screen into sections. On one side you can see our html as it is in our code and on the other side you can see how our html has rendered. So the host selector will have us scope the pd-drawer element. The root selector will have the parent of the pd-drawer. The content selector is used to scope the content tag. The shadow selector is used to select the content inside of another element, but only one level deep and lastly, the deep selector is used to scope all of the elements inside of the element selected.
Material Design
Material Design is a visual language developed by Google. Its inspiration is the study of paper and ink. That is why many elements look like and react like paper and ink. It is also heavy on animation, giving meaning to motion of the elements. For the full specs of Material Design you can visit the following site: https://design.google.com/. Google has done an excellent job in explaining the theory behind its new visual guideline recommendations as well as giving examples for components such as data tables. If you're using AngularJS, you can visit this library to easily implement material principles. You can download the following library, name the Material Design Lite developed by Google. This is independent and has the minimal CSS and JavaScript needed to conveniently wrap our applications with this design language. Lastly, Polymer has a palette of elements implementing the Material Design principles. These are called paper elements and with them we can build Material Design applications. For example, you can view the paper buttons that implement the ripple animation or the paper card implementing the paper effects. During this lesson we will be using many of these elements and we will even create our own elements, implementing the Material Design rules.
Summary
In this module we talked about styling in our application. We saw how CSS is used inside our elements and created the simple theme and coloring system. Lastly, we talked about Material Design and how it will be used in our application.
Routing
Introduction
In this module we'll set up the routing structure of our dashboard. There should be a way where different links will load different pages dynamically, as this is a single page application. In this module we'll set up a small system to do exactly that.
The Menu
Our site is going extremely well. We have a lot of moving parts nailed such as the application shell or theme, or color palette, and a basic drawer system working. It is time to add the left menu so we can browse to different pages. Our pages as seen in the first module are the home page, the profile page, the staff page, and lastly, a logout link. To implement menu I'll, of course, create an element to help me with this. Let us create a nice, reusable list element that we can use throughout our application. I'll create a folder named pd-list and an element pd-list-item.html. Now in the pd-list-item element let me add the dom-module element to declare the html part and the script where I'll add this element to Polymer and instantiate it. We'll add three properties: the position, icon, and url property. These will take the value of the attribute that the element wants declared. That is why I have the reflectToAttribute set to true in the property declaration. Now once the element is instantiated I want to make some checks, like to fine tune the properties if they are null or not set properly. In Polymer there are a number of events through our element's lifecycle that can help us with this. If we visit polymer-project.org, click on guides and resources, registration and lifecycle, lifecycle callbacks, you can find the events triggered during an element's lifecycle. Polymer first runs the created event once the element is added in its elements list. Then the local DOM is initialized. After that we have the ready event. The Factory/Impl callback is just another callback method run only when an element is initialized through JavaScript and not through html and the DOM module element that we have been using mostly in our application. Lastly, the attached callback is called. Going back to our element, we'll add the ready callback which will run after the local DOM is rendered and normalize some of our attributes if they are null or empty. To wrap up this element we'll add some styles and some html code in the template tack. (typing) This html will bind the position property with the divs class. Then it will bind the href attribute of our pd-list's items link with the url property. It will replace the content element with the content of our element, and lastly it will bind the icon attribute for the iron icon element with the icon property of the pd-list-item element. I'll open the pd-dashboard.html element now and include the pd-list-item element we created together. After that, I'll implement our method by adding four menu items. We'll refresh our main page to preview our results. Looking good! We can see our menu items there and once we click on them, we can notice our roots changing. In the next video we'll implement routing so we can load other pages as well.
Routing
Time to make our application more alive by dynamically loading different pages depending on our routes. I'll create another element as always to solve my problem. Let us name this one pd-flatiron-director as it will extend the flatiron-director library which you can download over here. I'll include this third-party library in my project. Included as a global scope in our application and add the boilerplate code for my new element. Then we'll add a route parameter and a router getter. The getter, once called, will return the global private_router object and if it is not set, will instantiate the flatiron router. Then in our ready callback function, we can add an event that will trigger once the router is changed and set that value to our local property. Also, on our first load, I'll set the route property and if it is empty it is can redirect to an empty page. It is time to add our external pages. Let us create a folder named pages and add the home, the profile, and the staff pages. In each page, I'll add some dummy text for now. I will return to the pd-dashboard element now and create a local route property. We can include the pd-flatiron element and add it in our pd-dashboard element. Now we'll bind the local route attribute with pd-flatiron-directors route attribute. So once the attribute changes, the updates will apply to our local route property and the observer will trigger. Observers are special methods that are triggered once our properties have changed, sending as parameters the old and the new value. In the next video we see how we can load each page dynamically.
Loading Pages
In bower.json we'll include the iron-ajax element and run bower install to include that element in our bower components folder. I'll include this element and add it in pd-dashboard as well. The iron-ajax element is very interesting as it works as an element that exposes network request functionality. If we visit the polymer-project.org and click on catalog, you can view here the complete list of Polymer's custom element library. The iron library contains the most basic elements. You can find the iron-ajax element over here and preview the documentation. Returning to our application now, we'll implement the iron-ajax element, and once the route has changed, we'll change the url with the page specified and run the generateRequest method to trigger a request. Then in the ready callback we'll add an event listener to handle the response. So once we receive back the page specified, we'll include the page's content to our main area. The self.$ is a selector that takes us in the template element and then we can select the template with its id. We have a div with the id main. The way to select that is with self that selects the element, the $ sign which is the template tag, and main which is the id of the div. Then we'll reset the content and append the new body content received from the request. For the header content, we'll select all of the links and loop through them. If our document doesn't have that resource already loaded, we'll add that resource to the head of our document. After we refresh the page and click on each link, you can see that we have our basic routing ready. Also, if you load a page, for example profile, that page is automatically selected and from there on the user would dynamically load data from each page depending on the route.
Summary
The last couple of chapters close an interesting chapter in our application. We went over so many basic principles of Polymer such as declaring, including, and implementing elements. The properties of our elements, computed properties, insertion points, CSS in our elements, and events. We also finished our basic application shell with routing as well. In the next module we'll go over authentication and create a simple login system.
Authentication
Introduction
Hi. This is Bill Stavroulakis and welcome to the fifth module of this course on authentication in our web application. In this module we'll create a simple REST service, secure our application, and create a simple login system.
Simple Backend JSON Server
In the previous modules we made some huge steps together. Through the implementation of our basic app structure you now know a substantial part of Polymer's basics. In this module we'll work with our site's REST service and authentication. Time to create a simple REST service so we can interact with our site's backend. I'll install a Node module called json-server. Let us add the library in our package-json file and run npm install to install the package. Then we'll go back to the app.js file and include and instantiate the json-server object. Then we'll make this service to listen to port 5000 and create a db.json file to add a big JSON object. The JSON file will work as a database representation so we can persist and collect data from. Let me run node demo-server/app.js again to run our services and visit local host 5000. The json-server package has read the db-json file and created a quick REST service for use where we can make get requests and receive part of our big JSON file. For example, if I run localhost5000/users you get a list of the site's users. Then if I run localhost/users/1 we'll get the user that has the id of 1 or we can make a more complicated request like localhost/users?username=bill, so we can get the user with the username Bill. We can also make post requests to persist data. For example, I have this post request ready. To change the username of one of my users from Chris to Joy. After running the post request let me run localhost5000/users and you can see the username changed. Perfect. Now we have our site running on port 8080 and our REST service running on port 5000. Time to add some security and authentication.
Simple Backend Security
I'll add two new packages in our package.json file named cookie-parser and express-session. Then I'll run npm install to install these two new packages. After that I'll visit the app.js file and load my two new packages. We want security on the JSON service and on our app as well, so I'll inform both packages to use the cookie- parser. Instead of security you have to add your own string with high entropy as the cookie-parser will encrypt and decrypt the cookie data received from the user, depending on that string. Also, in our json-server object I'll add my own use function, to check whether or not the user requesting the data has a signed cookie. If not, we'll redirect him to the authentication page. If he does, we'll allow for the next step to continue. We'll do a similar method to our basic application by filtering the request and forwarding the user depending whether he has a valid cookie or not. When the user tries to load the authentication page though, we'll have to bypass the security feature and serve him the authentication page whether he has a cookie or not, since he'll have to access it with no security. Finally, I'll create an empty authentication page for now, just to test if the authentication process is working. Let us run node demo-server/app.js again to run our two services and try to enter the localhost8080 page. You can see that we are redirected to the authentication page. The same occurs with our localhost5000 page as well.
Login Page
In the previous video we saw how we can secure our pages but also serve the authentication page when the user doesn't have a valid cookie in his requests. In this video we'll work on our authentication page to offer the ability to the user to log in into our site. First, in the auth.html page I'll add some standard boilerplate html. This is our standard html code boilerplate with our head section and our body section. The only difference is that we'll include the components lite library to enable the rel import tag and include with the rel import our auth dialog component. Lastly, we'll include the component in our body section as well. Then I'll create a new Sass file named auth.scss and add some custom CSS. This SCSS will be used to style our auth-dialog. You can find this file in the demo files or you can post the video and copy the code. This SCSS file will also compile to a CSS file. For more info on this you can preview the styling module of this course. Then, I'll open gulp file and add the new task to compile this SCSS file. After running gulp sass to compile the Sass code I'll create another file named auth-dialog.html to create a new element in that file. Again, I'll include some standard boilerplate code used for my elements. Then we'll add our theme CSS, the auth.css and include some other elements as well. These elements included our elements created from the Polymer team. You can visit the following site, elements.polymer-project.org for the full list of elements and include them and reuse them in your projects as well. We will be using numerous paper elements that comply with the Material Design principles out of the box. To download the files necessary for this to work in our project we'll have to include them in our bower-json file and run bower install in our console. If we open bower_components we can view these libraries loaded, so we're ready to go. Time to add some html in our element for our login form. This section is pretty straightforward. We have two input tags, one for our username and one for our password. A remember-me checkbox and lastly a login button. These elements, the paper input, paper checkbox, and paper button are included in our page from the import tags and are installed with the bower-json script and command seen in the previous part of the video. If we reload the page you can see a clear material design card in the center of our page, with the paper inputs, the paper checkbox, and the paper button. Also, we'll add a user property with two-way data binding enabled. When you bind an object element, you can bind specific properties of that object. As seen here, we'll bind the username with the value of the input element and the password with the other input element. In the ready callback of our element, we'll focus the cursor to the username input tag located in the username paper input tag. It looks like we have everything set up. Time to add our login logic in the next video.
Login Process
I'll open the app.js file and add two code snippets. The first one is for the login post request. We'll collect the username and the password from the parameters of the request. Then we'll go through our users in the db.json file and see if there is a user with those credentials. If the user exists, we'll create a cookie for that user and return it in our response. Also we'll send a JSON response that the request was successful. If the user isn't found, we'll send an error response. The next code snippets are some headers added in every response of our json-server service so we can enable CORS in our service. CORS stands for cross origin resource sharing and that is needed since we'll send requests from our site which is on localhost8080 to our REST service which is running on localhost5000. I'll also add a logout handler, so when the user visits the path/auth/logout, we will clear the cookie and redirect him to the authentication page. Returning to our application, I'll add the iron-agents element so we can make the post request specified to make a login request. I'll also include the paper toast element which will be responsible to display toast messages to our users. Then on our login button click, the login method is called. Let us create that method and make the request from that method. We'll set the username and password parameters in our request from the user object and then run the generate- request method located in our iron-ajax element. Once the request has a response, the on-response callback is triggered, which is our login callback method. This method will receive a response parameter as well. From the response parameter we'll locate the JSON sent from the server, then we'll add an if statement. If the login is successful, we'll redirect to the homepage; if not, we'll show the error message sent from the server as well. Let us refresh our page and try an example. As a username I'll add bill and as a password polymer2. Once I click on login and since these credentials aren't the correct credentials we'll receive an error message. If instead of polymer2 I add polymer, we'll get redirected to the main page. We also have the user session cookie sent which you can preview now in our local cookie collection, and now we are successfully authenticated in our application. Lastly, if we click on the logout button, we can see that we have successfully logged out of our application and have been redirected to the authentication page.
Summary
In this module we made our application more dynamic by adding a simple REST service and we connected our application with that service by creating a simple authentication system. We also secured our application from unauthorized users. In the next module we'll progress our application further by reading and updating our profile data through our profile page.
Profile
Introduction
In this module we'll implement the profile page. In the profile page we'll first the user's data and offer the authenticated user the ability to update the ability to update this data. We'll also create a new dropdown element.
The Card Element - Template If
A very popular UI item in Material Design are the card elements. If you visit the following link you can learn more about the card element and how it is used. We'll create our own card element so we can reuse it throughout our application. As usual, I'll create a folder and the html file to host my element. Then I'll copy and paste the code I've written for this element. By now you should be very comfortable with the Polymer element structure. I have the style tag located over the template tag to style my element. Then we have the template tag to store the reusable code used each time we use the pd-card element and after the dom-module declaration, I have my script with some simple logic to set the fin classes if the fill attribute class is set. A new feature we'll introduce are the conditional templates. In our code, we'll want to show or hide html, depending on the status of various properties. In our pd-card element, we'll want to show or hide the header depending on the head attribute. By adding a conditional template, if the head of our element is set, this block will appear. If the head element is not set, this block won't appear. To view the full code of the element you can check out the demo files of this module or the polymer-dashboard.com project. In the next video we'll begin to work on our profile page.
Reading the Data
In this video we'll begin to work on the profile page. We'll include an element named profile-edit and add that element in our page. Now we'll create a new file named profile-edit.html to declare that element. In the profile-edit.html page I'll include the element boilerplate, then I'll use the pd-card element we created in the previous video. In the pd-card element, I'll add as content the form that I want to create. Also, let me add a head with a string profile details. If we revisit the pd-card element, you can see that the content that I added will be rendered in this section and the head will be written in this section. Last, I'll add a paper-toast element to show notifications, and the standard Polymer script. In the properties section I'll add a profile object and as a value of my input tag I'll bind the properties of that object with certain values. We'll also have to include all the other elements that we'll be using in our profile-edit element. Now when everything is ready, I would like to get the data of my user and show them in the form. Let us open the app.js and create a path where the user can get his profile data. We will get the user id from the site's cookie. Then we'll loop through our users until we find that user and return his data as a JSON string. Let us see what we have done until now. I'll restart my server and first of all, visit the site localhost8080. Then I'll click on the profile page and viola! I can preview my form with a nice save button. Then I'll visit localhost5000/profile and I can view the data of my profile as a JSON string. Time to combine these two and preload our data in our page. In the profile-edit element I'll add the iron-ajax element again, which will trigger our get request and have the getProfileCallback method callback. I'll include that callback and set the profile object to the JSON profile returned. And of course, I'll trigger the getProfile once the element is ready. After I reload my page, you can see that my profile data is preloaded on the profile page.
Dropdown Element - Template Repeat
In my profile data, I have two properties that I haven't included in my form yet and that is the status which is active or inactive and the type which is either principle itadmin or teacher. I would like to create a nice dropdown for these properties. We could use our standard HTML5 select tag, but I want to create a more cool reusable select tag. That will be more Material Design-like and we can use throughout our application. I'll visit my components folder and create a new folder for my new select element named pd-select. In the pd-select folder I'll create a pd-select.css and a pd-select.html file. In the pd-select.css we'll add some CSS for our element which you can find in full in the demo files of the module and in the pd-select.html the element boilerplate code to declare our element. I'll include the pd-select.css in my element and the style tag with CSS variables, which we declared in the styling module. Then we'll add our selection wrapper and in the scripts section we'll create a new array property with the notify property set to true and the reflectToAttribute property set to true. Previously we saw the template if tag together that depending on the status of the value, it would either show or hide the html snippet in that tag. Now we're using a template repeat tag. This template repeat tag will loop through the options array and for each item, it will display that item on our page. To see what we've done until now, I'll include the pd-select element in our profile page and add a pd-select element with the options of active and inactive. If we refresh, you can see the two options appearing on the sides. This is done because the template repeat tag looped through the options and for each one, it added a new div tag. Also, the second select tag appears on our page as well; however, it is hidden behind the active and inactive select tag. We'll fix this in the next video.
Dropdown Element - A Cooler Select Element
Let us break down HTML5 select tag. At the beginning, the select tag shows us a friendly select reminder if we haven't selected anything. Once we click on it, we see the toggled open state with the options displaying and once we click on an option, we see the toggled close state with the options hidden and the value selected to appear as a selection. At this point, I'll add some more attributes in my element to mimic this functionality. Let me start with a label and the value properties. Also, a computed property named SelectedEmpty which will return true or false if the value is null or not. I'll select the toggled property so we can set the toggle status to closed or open. And a toggled class computed property that will return the correct class depending the state, and either show or hide our options. Over the options section I'll add this code snippet. (typing) This will display the label property set in our script section. In Polymer there is a special attribute named hidden$. With this, if the property is set to true it will hide the element. So we want to hide our label if the element isn't set. If we haven't selected the value yet, we want to show a friendly message as well and if the selected value isn't empty, we'll display that value. Lastly, I'll add a data-select$ attribute in the div of my options loop tag. The data-something? attribute is used so you can save data in your html, so you can recollect it when needed. So once the user clicks on an option, the select element function is triggered. In this function we'll collect the target of our div clicked and get the data-select attribute. Also, we'll set this toggled state to close, to close the options section. Lastly, we'll add the toggle function so we can interchange the toggle value to either hide or show the options. This toggled function is triggered from this on-click event. Time to revisit the profile element. In the pd-select element now, I'll add the label attribute and bind the value attribute to the profile type property and the profile.status property. If I refresh the page now, we can see that the values are preselected. The label appearing as well, and once I click on the select, I can view my options and change them. Things are going great. Next, we'll continue with the save button and make it save any changes we apply to our profile.
Updating the Data
The profile page is almost ready. We'll only have to make this save button work so we can persist any changes we make on our own form to the backend database. I'll add a new iron-ajax element with the settings needed for us to save our profile data. The url where we'll post the changes is the localhost5000/profiles. It is a post request. The with credentials will send the cookie in our head so the server will know who the authenticated user is and a response callback that will trigger once the request is done. Then when the user clicks or taps on the save button, we have an event set to trigger the saveProfile method. I'll create the saveProfile method to handle this event. We'll attach in the body of our request the profile data and set the content type of our request to application JSON. Then we'll trigger the request. Also, I'll add the saveProfileCallback method which will trigger after the request is done where we'll show a success message to the user. I'll refresh the page and open the Google debugger. Then I'll change the name from Bill to Billy and click save. We can see the success message. In our network tab, you can see the post request made. The request header has various standard settings set and the encrypted cookie with the authenticated user's information. In the body of the request, you can see the JSON object sent and as a response header, we can see the various attributes set for cross-browser requests and other standard information. Once I refresh the page again we can see the name set to Billy. Also, if we call our REST service, we can see from there again that the data has persisted on the back end.
Summary
In this module, we finished the profile page by previewing and updating the user's data. We also created two new cool reusable elements, the pd-select element and the pd-card element. We are now in a position to implement a more advanced grid system. In the next module we'll finish the staff page by creating a more complicated page with a grid to view, create, update, delete, search, and sort the staff list.
Staff List Page
Introduction
Hi there. In this section, we'll create together the staff list page. This will be a grid with the staff information where we'll list the staff, create a new staff member, update the info of a staff member, delete an item, and search members by their username. Let us dive in.
Reading the Data
In this video, we'll create the staff page, our grid, and list the staff data. The first step is to create a folder named staff. Our html page staff.html, html page for our element, staff-list.html, and the staff.css file. In the staff.html I'll include the staff-list element and add the staff-list element. Now in the staff-list.html element page I'll add the element boilerplate and include the elements I'll use in this element. I'll open the staff.css page and add some custom CSS, and include the styles in my element. You can find this code in the demo of the module. The next step is to include some styles with my global variables. Let us add the pd-card element and in this element I'll set my grid. The grid has a head section and a body section. The head section works just like a html table would and the body section has a template loop that loops through the profile array and for each item will display the appropriate properties. The third step will be to include the iron-ajax element so we can make an AJAX request at my REST service with that element and get the profiles necessary to display. If I load the path in my browser you can see the JSON array that is returned. Time to load this in our code. I'll create two new methods. The searchProfiles and the searchProfilesCallback. In the ready method callback, I'll call the searchProfiles method and in this method I'll trigger the iron-ajax request. The iron-ajax request will handle the request at the url specified and once we have a response it will call the searchProfilesCallback method with the response. In the searchProfilesCallback I'll associate the response data with the profiles array and for each item in the array, I'll set a new property called selected. After reloading the page, we can successfully view the list of the staff members. This grid could use some more improvements such as pagination, but for this demo we'll keep things simple. Things are looking great. In this next video we'll see how we can set up a create form to add new staff members to our list.
Creating the Data
In this video we'll create a mobile friendly form to add new staff members to our list. First of all, in my elements properties I'll add two new properties named editModel which is an object and panelToggle, which is a string. In my elements template I'll add the panel snippet. In this snippet we have the binded class attribute which changes the divs class attribute according to the panelToggle parameter. In the body of our panel we have a form where each value is binded to a property of the editModel object. Also, it has two buttons, the save and the close button, where the save button will be used to save our form and the cancel will be used to close the panel without saving. Then in our grid section I'll add an options line to add various buttons for my grid. In this section we'll include an add button to open our panel. This button has an on-tap trigger that will run the openPanel method every time we click on the button. The last element that we'll add in our template is another iron-ajax element, used to trigger a save request to our server to persist the save data. This is a post request at the following url and once the request is done, it will trigger the saveProfileCallback method. At this point we have four triggers unhandled. First, the on-tap method named openPanel to open our panel. The second, the saveProfile method to trigger the save action. Third, the closePanel trigger to just close the panel. And last, the saveProfileCallback method to do something once a new staff member is added. I'll start with the open panel to show my panel. To do this, I'll just set the panelToggle property to toggled. Also, I'll instantiate the editModel object. As seen previously, the panelToggle property is binded with the class attribute over here, so it will set the class to the string toggled. If we view in our CSS, we can see that the edit panel which has a parent with the class toggled, will move the panel to the X axis from -200 to 0. Then, in the closePanel method I'll set the panelToggle to empty so that will change from 0 to -200 again. Let me refresh my page to see the results. Once I click on the + sign, the panel glides into view and once we click on the close button, the panel glides out of view again. Now we want to save our member when the user clicks on save. In the saveProfile method I'll set the body of my request to the editModel object. Set the content type to application JSON and trigger the request. Once the request is done, the callback is triggered where we'll set a toast message, reload our list, and close the panel. Lastly, let me add the paper-toast element as well in my page. I'll refresh my page and click on the add sign again. Let us add some dummy data and click save. (typing) The new user is added, the toast message is displayed, and the panel closes. In my debugger you can see the post request set the iron-ajax element. In the body of the request is the new user in JSON format and we can have a response of that user with the new id which indicates that everything went as expected. Then we can see the get request again that is triggered to refresh our list. Also, you notice an options request before my post request. This is just something that iron-ajax elements does which works as a ping before the post to be sure everything is okay with the server before it sends the data. In the next video we see how we can update the data of the user that is already in the list.
Updating the Data
For each user in our list you can notice an edit button that binds the id of the user with the data id attribute and once clicked, it triggers the openPanel method again. I will expand my openPanel method to handle this functionality as well. From the event object we'll get the html node where the event was triggered from. From that element, we'll get the id from the data-id attribute and set properties of the editModel the same of those from our profile list that has that same id. If the data-id attribute doesn't exist, then the id value will be null, so then we'll reset the editModel to empty values. If I go back to the html section of my element, you can see that when the user clicks on an add button, the openPanel method is triggered, but the data-id attribute doesn't exist so the values will be empty, but at the edit button, the data-id has the value of the staff member's item, so the edit-model will be this item. Last, when the user clicks on the save button, then we don't have to do anything because we'll send to the server the editModel item again which will be the updated data of the user. To preview this in action, I'll reload my list page again and click on the edit button. Change the type from itadmin to teacher and click on save. In my debugger you can see the post request made with the data of my user. The server will know that this is an existing user because we have the id property set to a preexisting value. Now if I click on the add button and add some dummy data, click on save, (typing) you can see the same request made, but the id property doesn't exist so the server knows that this is a new user and add the user in our database as a new user. In both cases, after the request, the list refreshes. We're going very well, as we can create, read and update our staff list. The last step is to be able to delete a user so we can have a simple, crude implementation set.
Delete Items
In this video, we'll add the delete functionality to our grid. In our loop we can see that each item has a selected property that is binded to the paper-checkbox element. So every time we click on an element, the selected property from false is set to true. We'll add a new item in our options section, which will trigger the deleteProfiles method. Last, for our html section, I'll add a new iron-ajax element with the information needed to our delete request. The url is the localhost5000/profiles path again, but the method is delete and the response callback is the deleteProfilesCallback method. Time to handle these two triggers. The deleteProfiles method which is triggered from the delete button, will loop through the profiles and if one is selected, it will add the id of that user at the end of our url and trigger the request. In our callback method, we'll show a toast message and refresh our list and close the panel if it is open. You can, of course, improve this section by creating an array and making the request once instead of making different delete requests for each member you want to delete. Let me refresh the page and select the two items we added in the previous videos and click on the delete button. We can see that these two items have been removed successfully. If we call our REST service as well, we can see that these items have been moved from the backend as well. Now that we have a basic grid where we can list, add, edit, and delete an item from a list, it is time to push the envelope a bit forward and add a search feature.
Search Element
In this video we'll include a search feature in our grid. I'll make this section a bit more advanced since by now you should have a really good grasp on how things work. In reality, when you're working with Polymer, you want to break things down into small, reusable, testable, and independent components. So I want to add a search component to my list. This will basically be a search button that once clicked, it will take all of its parent's element's space. Then we can enter some text and click on the enter button to search or click on the exit button to close the search box. I'll create a new component named pd-search that will have this functionality. As always, the pd-search.html will have the element boilerplate code to instantiate my element. I'll include the other elements needed and move on to my dom-module section. I'll include some custom styles. You can copy and paste the styles from the demo files of this module. In the template tag of our element, for now we'll just add a search button. Let me include the pd-search in my list page and add the element in the list options. After refreshing the page, you can see the search button there. Of course, if we click on it, nothing happens. I'll wrap the button with a div and bind the class attribute of that div with the overlayClasses property. I'll also add the search-form in my wrapper. In my properties section I'll include the search-enabled Boolean property and the overlayClasses property. The overlayClasses property will be computed, triggering the computeClass method dependent on the search element property. Every time now the search enabled property changes, the computedClasses method will be triggered and set the overlayClasses value to search overlay, if the search-enabled is true, else it will set it to search hidden. In our CSS when the search-hidden is visible the search-form is hidden and when the search-overlay class is visible the search button is set to the left of our box. When the search button is clicked we'll add a method named search to handle this event. In this event we'll set the search-enable to true. Focus the input in our input element and set the value to empty. Last, when the close method is triggered, we'll set the search-enable to false. I'll refresh the staff page to see the search box in action. Once we click on the search button, you can see the search box appearing and once we click on the x button, you can see that the search box disappears.
Search Element - Custom Events
In this video we'll see how we can connect the pd-search element with our list. I'll include a special element created by the Polymer Team named iron-a11y-keys. With this element we can set a target and once one of the keys set is hit, a method will be triggered. In our case we'll target the search-form div and once the enter key is triggered, while we are focused in this div, the search-action method is triggered. Now in the search-action method we'll run the fire method. If you visit the following path, you can find some helper functions by Polymer. The fire function fires a custom element. The first property is a string first to declare the event name. In the second property we can add any custom values we want to pass over through our event and the third property are some other special properties such as bubbling and other special parameters we can preview here. Going back to our code, we can see that the search action will fire a custom element with the name of search and as a value, the value of the search input tag. Also, we'll fire a searchClosed custom element once the search box is closed. To handle these events we'll have to add two event listeners in our staff list page. These handlers will be attached to the search elements. In the fire element, the this section indicates the whole element so the handler will be attached to the pd-search element as well. So let me return to the event handler. In the callback function, the event variable is passed that has many interesting properties. The detail property is the custom variable passed from our fire events, which in our case is a search value. We'll run the searchProfiles method passing this value. In the searchClosed event, we'll just run the searchProfiles method to refresh our list. Lastly, I'll expand the searchProfiles method to handle a search parameter. I'll add the parameter in my inputs. If the search parameter is not null, we'll add the parameter in our request for our username. If it is null, we'll reset the parameters. Time to see if everything is okay. I'll refresh the page and click on the search button. Let us add Bill and click enter. You can see the filtered list. If I add joy and click enter, the members with username with joy appear. Once we click on the x button, the search form closes and our list refreshes with no parameters as expected.
Search Element - Reuse
In this video we won't add a new feature but I'll just show you how we can reuse the search element we just created. Let us say that we want to add a search feature on the header of our page. We'll see how easy it is to do this while reusing our component. I'll open the pd-drawer.html element and include the search element. Then I'll add the pd-search element on the toolbar of my page. Have in mind that the element has the id of search. I'll refresh the page to see what's going on. You can see the search icon on the right of the page. Once I click on it, the search form appears and once I click on the x button, it disappears. Once I click on the search button in the list page we created previously, we can notice the same functionality. With this example, you can see in action how we can use the same element we created together in two parts of the page. These are two separate entities with the same functionality. To handle events in our header's search element, I'll add two event handlers in my ready callback. These handlers are attached on the search element. To select the search element you can write this, which is the whole element, the $ which is the template element of our element, and the search which is the id of the pd-search element. For now I'll add two console.log methods to write messages in the debug console. I'll reload the page again and click on the header's search element again. Once I enter some text and click on the enter button, you can see the search term in my console.log. You could do anything you would like from here on, either load a search page, filter a search term, anything. Lastly, once we close the search, you can see the closed message in the console log, meaning that the closed event was triggered.
Summary
In this module we put together a grid with some basic crude functionalities where we can create a staff member, read a staff member, update the staff members, and delete the staff members. Lastly, we created our own search element for our staff list and we saw how we can reuse the element in other parts of the page. In the next module we'll see how we can construct a simple chat system in our application.
Chat
Introduction
This is the last module of this course concerning features of our application. We will list our friends on the right panel of the page and once we click on of our friends, we can chat with them. To make this possible we will see how we can add real-time functionality to our application and how can we create a simple chat system.
Showing Friends
The first step for a chat is to list the friends or list the people that we can chat with. I'll open the pd-dashboard element and in the properties of our page add an array that will include our friends. Also, we'll add an iron-ajax element that has the details needed to make a request to the server to obtain the data of our friends. The url is localhost5000/friends. It is a get request and once the data is received we'll call the getFriendsCallback method. We'll need also our profile information so I'll add another iron-ajax request. The iron-ajax element has an attribute for auto which means that it will trigger a request automatically once the element is loaded and once we have the response it will call the getProfileCallback method. Let me copy the url of the request and make the request from our browser to see what data will return. From this request we'll need the username so we can use it for our second request. The second request will call the localhost5000 friends url and add as a parameter the username retrieved from the previous request which is Bill. So once we call the url you can see the friends of the user Bill. Time to do this in our code. I'll first create a method for my callback and grab the username from that response. Then we'll call the getFriends method where it will set up the username parameter in my request and trigger the getFriendsRequest. Last, from my callback I'll set the friends property to the array of friends from the response and for each of those items set a url parameter. To show the friends loaded in the right drawer I'll create a template repeat element in the right menu section and add the pd-list-item element for each item in the loop, by adding the url attribute with the url parameter set and the name of my friend. After reloading the page you can see the friends of the user appearing on the right of the page. If I click on one of them, nothing happens, as we haven't created the thread page yet. We'll create that chat page in the next video.
Chat Page
In this video we'll create the thread page. I'll create a new folder named thread and in it three files, the thread.html which is the page loaded, the thread.css to save my styles, and the thread list which will be the element loaded in the page. In the thread.css I'll add some custom CSS. You can find this code in the demo files of this module or in the polymer-dashboard.com project. And in the thread.html I'll load the thread-list element with the link tag and add the thread-list element in my page as well. In the thread-list element page I'll insert the standard element boilerplate code and include the link of the elements I'll be using. I'll include the CSS file and some custom styles using the global CSS variables we have set in the stylings module of the course. Now the chat page will have two sections. The first will loop through the messages and display some data such as the user, the message, and the date time of the message, and it will have a footer section which will work as an input for us to write our messages, and a send button to trigger the send message event. In the properties section, I'll Active Directory the messages array to carry the messages in the thread, a message string which will be the message we'll be sending from the input tag, our username, and the conversation key. In the bottom of the template element we have added a getProfile request to trigger automatically and once we have a response, the getProfileCallback method will be triggered. In the getProfileCallback we'll set the username from the response, instantiate the message and get the username of the person we're chatting with from the url parameters of the page. Lastly, we'll create the conversation id which will be the username of the users in the conversation in alphabetical order. This way both sides have the same id while chatting. In this video we created the basic structure for our chatting mechanism. In the next video we'll see how we can send and receive data in real time.
Socket.IO
In this video we'll install and set up socket.io. To make a web application have real-time features you have to use a pile of techniques such as long-polling, the Forever-frame technique, server-send events or WebSockets. To learn more about the basics of real-time web applications you can view my course with the title, Real-time Web Applications, to dive deep in the theory behind these techniques. Usually we don't have to dive into these techniques but use high-level libraries such as SignalR for .NET applications or socket.io for NodeJS applications. Since we're using NodeJS for our backend we'll be using socket.io. To do this, we'll have to open the package.json file and include the socket.io library. Then we'll run npm install to download the package. After that we'll open the app.js file and scroll to the end. I'll instantiate the I/O object, adding as a parameter the http server. Then after a client has connected we'll add two event handlers, the on subscribe and the on chat message. These two handlers will be triggered from events emitted from the client side. The first one is to subscribe the user in a room. The second one is to broadcast the message to the members of the room, so we'll parse the message to JSON format and emit a private message event to the client side of the members of the room when the user sends a new message. The server side of our code is ready so we'll go over to the client side in the next video. For more information on socket.io you can visit socket.io or its GitHub page at: github.com/socketio/socket.io.
Updating Data in Real-time
Now I'll go to the client side. First of all we'll load the socket.io client library. Then we'll create a socket object in our properties. We'll instantiate it in the getProfileCallback method which as you remember runs automatically once we have the user profile information. Then we'll emit the subscribe event with the conversation id. After that we'll create an event handler for the private message event sent from the server. This handler will trigger every time the server receives a new message for the room. So we'll parse the message, push it in our messages array and scroll the wrapper to the bottom. You'll notice that the scroll code is located in this function. The async is used in Polymer to run code asynchronously after x amounts of milliseconds. I've added the scroll code in an async method so the rendering of the new message we just pushed can be rendered before we scroll. We finish the part of the code where we subscribe into a room and receive messages from the server in real time. Time to create the functionality of sending a message. You remember that we had a send button. Let me see what method does that trigger. It triggers the sendMessage method. I'll create that method in my scripts section. First of all, I'll add the check not to do anything if the method is empty. Then we'll get the date and time and stringify a JSON object with the parameters of the user, the room, the message, and the date. We are stringifying the JSON object because we have to send strings to the server. Then we emit the chat message event to the server with that string and reset the message. I've split the screen in two for you to view the server side and client side. You can see that first of all the user will trigger the subscribe event from the client to the server. Then once it triggers the chatMessage event from the client to the server that will trigger the private message event from the server to all of the subscribed clients, so it will update to all of the clients. Time to view our demo in real action. I'll run the server and reload the page. You can preview my friends on the right panel of the page. Now I'll open a new private tab and log in as the user Joy. You can see her friends as well. I'll click on Joy in one account and Bill on another. When I send a message from one account, you can see that it is appearing in both windows instantly. Now if I click on another friend, let's say George, you won't see the message in the conversation with Joy, which is logical since this conversation has the id of bill-joy and the other one has the id of bill-george.
Summary
In this module we created a very simple chat system and added real-time functionality in our application. There are some security optimizations that you can consider making such as setting up the subscription on the server side and adding authentication checks on the server side as well, but we can leave this simple demo as it is and you can take it from here. This was the last feature of our application and we could send it to our client as it is right now; however, in the next module we'll talk about performance and optimization to make our application faster, smaller, and more stable.
Performance and Optimization
Introduction
In this module we'll talk about performance and optimization. Our application may look like it's done; however, there are some techniques left for us to improve its speed and make it smaller. Also, we'll have to add some tests for the durability, longevity and stability of our application.
Vulcanization - The Problem
In this video we'll talk about vulcanization. If I open my index.html you can see that we first import the pd-dashboard.html element and then we use it in our page. In the pd-dashboard page we include various other elements. Now in each of these elements there are various other includes as well, not taking into consideration all of the CSS and JavaScript files as well. It won't be hard to imagine that this leads to numerous requests to our server so we can load all of the resources needed. I'll load my page, open the debugger, and reload the page. You can see that numerous requests were made to our server and a lot of kilobytes were transferred. All of these requests are the elements and resources included in our page. In the next image you can see how a simple http request goes through. The client makes a request to the server and the server responds with the data requested. This whole process is resource heavy. First of all, with every request there is a huge chunk of meta-data such as headers and other transfer data. Secondly, there is a wait time for the request and the response to take place, as the request has to pass all of the routers, switchers, servers throughout the world to reach its destination, collect the data, and back. Lastly, with each request made the server has to probably create a new thread, make calculations, process data to return the response. To make matters worse, with http 1.1 the request response process isn't always done in parallel and browsers try to issue multiple TCP connections to try to increase speed, so we would load our site. Then the site would need resources and make new requests and these resources would need other resources, making even more requests. This way we would overload the wire, make the site slow, and the server much less performant. How could we ever solve this problem? The answer is vulcanization.
Vulcanization - The Solution
With vulcanization we can run a compiler script on the html file of the element we wish. This script will go through the element and find all of the resources needed. Once it finds a resource it will load it and append it in the file. It will run this recursively in the elements included as well and it will find resources in them, it will append those as well. This way we will have one big html file instead of tens of small files. I'll open the package.json file and add the gulp-vulcanize task. Then in the gulp-file.js file I'll include a copy task which will copy the pd-dashboard element and paste it to the new file, pd-dashboard.vulcanize.html. Then we'll set up the vulcanize task to run the vulcanization process on the pd-dashboard.vulcanize.html file. In the exclude array I'll add the files I want to exclude from the vulcanization process. Usually we want to load the Polymer project externally, to load asynchronously. Then we'll set some more properties such as stripComments if you want to remove the comments from our code, inlineCss to embed or not the CSS reference in our page. I'll set this attribute to false so I can load them externally. InlineScripts to embed all of the scripts in one page and finally scriptExcludes to exclude some scripts from the vulcanization process. For the full list of properties and accommodation for the gulp-vulcanize task, you can visit the following link. We'll also have to include our vulcanize task in the default run sequence. I'll open Git Bash and run npm install to download the module. And then run Gulp to run the vulcanized task we just created. Lastly, in the index.html file we'll load the vulcanized file and not the pd-dashboard-html file. If I open pd-dashboard.vulcanize.html, you can see a big html file with all of the resources included. I'll start the server now and refresh the page. Everything has loaded as usual. You can see that the requests are fewer. Imagine now thousands of users using our site. We have saved thousands of requests from our server, making our site faster and relieving a great load from the wire.
Gulp Tasks
Now that we've minimized the requests needed to load our site, we can run some tasks to compress our site. I'll add two new tasks, the gulp-minify-html and gulp-minify-inline. With these two tasks we will compress the html file and its scripts and CSS of our vulcanized file. I'll run npm install to install these modules. Next, we'll write two Gulp tasks for these two new modules. I'll instantiate the minify-html and the minify-inline packages. Then I'll create the following tasks to run on the pd-dashboard.vulcanized.html file. These tasks will minify the html, the CSS, and the JavaScript text in the file. Lastly, we'll add these tasks in the run sequence after the whole process is done. I'll open the Git Bash terminal and run Gulp to run all of my Gulp tasks again. Then when we open the pd-dashboard-vulcanized file, you can see that it has been minimized, uglified, and processed. Once I reload the page, we can see that not only the requests are much fewer, the size of the page loaded has been minimized as well. This process never ends. You can always find new methods to optimize your resources and time needed to load your web applications. For more info, you can view the course, Website Performance for more techniques.
Testing
Except of optimization, it is necessary to create tests for our application as well. With tests, we can always know if our elements are working, if updates and new features created breaking changes. It is also a successful method to parameterize how exactly we intend to use our elements. As usual, we'll open the package.json file to include a new Node module. This one will be the web component tester. Also, we'll be needing two JavaScript libraries as well so I'll open the bower.json file and include the libraries needed in there as well. Then we'll run npm install to install the Nodule modules, and bower install to install the bower components. The Web Component Tester library basically uses Mocha which makes asynchronous testing simple and allows for accurate reporting while mapping uncut exceptions to correct test cases. It also uses Chai, for assertion styles you may want to use such as expect, assert, or should. Lastly, it uses Lodash and Async to make our lives easier and the code more performant. The first step in creating our html best component tests is to create a test holder. Then I'll create an index.html page with the following code. This html code just lodes the Web Components Library and the browser.js library in the Web Components Tester. This will load any test suites we have created. Then we'll create a file named pd-list-test.html so we can test the pd-select component. We'll load all of the necessary libraries in the head as well as our pd-select component. We'll wrap all of the code we want to test in a special element named text-fixture. On the script side of our page, we'll create a test suite and on setup we'll load the fixture and set the list object to the data set in the fixture, so we can reference it quickly. Then in our test suite we can create as many tests as we want. I'll create a small test for now to check if the options are set correctly. So we'll set the options in my pd-select element. After we make any changes, the flush method will run after any pending events or observations take place, so we have the final state of our element. In here, we'll get the lines created in the pd-select element and these lines should correspond to the count of the options we passed in. Lastly, we'll run the done method to tell our testing library that the test is done. Let us run the test to see if it will pass or fail. I'll run my server, log in, and go to localhost8080/tests. We can see our test running and fortunately it has passed with flying colors, so you can take it from here and create as many suites and tests you want to make your applications much more secure, documented, and reliable. I know that testing is a huge subject that can probably have a course of its own. For more info you can visit the Web Component Tester page or the text-fixture element page to dive in deeper.
Summary
In this module we didn't add any more features to our application. We went although through some performance issues we may come across and saw ways to solve them and optimize the application. Lastly, we saw how we can create tests for our custom elements and make reliable and performant Polymer applications.
Caveats and Resources
Introduction
This is the last module of this course and we'll talk about why you may not want to use Polymer in your applications. We'll also go through the interesting differences between the Shady DOM and the Shadow DOM. Lastly, I'll list resources where you can continue your journey on Polymer and that you may find helpful to learn more on this subject.
Browser Compatibility
A first reason you may not want to use Polymer is browser compatibility. If you visit the browser compatibility matrix, you'll notice very quickly that Polymer wasn't created for old browser support in mind. It basically works perfectly for IE11 and above and for the latest version of the other browsers such as Chrome, Firefox, and Safari. Most features work on IE10 as well and I've made some small demos work on IE9 as well. So if you are intending to use Polymer for the general public, you must have this in mind. If you use Polymer for a more controlled group of target groups that consist of mostly experienced users, you won't have a problem. For more info about browser compatibility, you can follow the Polymer team as they make more updates on this issue.
Shady and Shadow DOM
In this video, we'll talk about the difference between the Shady DOM and the Shadow DOM. Until now we saw the process of declaring an element and reusing that element whenever needed. Also, through insertion points we could have our elements with a very clean structure and in the background the element would wrap the html, style it, and add logic to it appropriately. Our elements also have only local scope, meaning any styles, scripts, or html in our elements had scope only in that element. Two ways to make this possible is through the use of the Shady DOM or the Shadow DOM. I'll open the debugger and view the html of the page. In my code previously you remember that in the index.html page we had the pd-dashboard element. Now in the pd-dashboard element we have various items that are in scope of this element. Polymer will automatically add a class named pd-dashboard in all of the elements in its scope, so it can style only those elements and the properties, events in JavaScript scope will reference only the DOM items in scope. This class system in the Shadow DOM method mimics in Polymer the real deal which is the Shadow DOM. We'll analyze this method now. I'll load my index.html and add these two lines of code in a script tag. These will set Polymer to use the elements as native web component elements and scope with the use of the Shadow DOM. Now after I refresh the page won't great and this is because I haven't optimized my CSS to work with the Shadow DOM method, but let us see what's going on under the hood. Once I expand the pd-dashboard I can see the shadow-root node underneath. This is the Shadow DOM, meaning anything inside here is truly encapsulated in this element. Once we expand, you can view the content of the element and any styles declared in the element are only set in the element without overflowing. The same occurs with events, JavaScript and references. I talked to you in this video about the difference between the Shady and the Shadow DOM, because Polymer by default uses the Shady DOM method. It is not recommended to enable the Shadow DOM polyfill for older browsers or for browsers that don't support Web Components because you will see a significant drop in performance.
SEO
Google announced recently that it is deprecating its AJAX crawling scheme and now it can parse JavaScript heavy sites that load dynamic content. That is great and certainly a huge step forward; however, for the Shadow DOM in Web Components, things aren't that sure until now on how optimized the rendering will work for the bots I would recommend for websites where SCO is vital not to use Polymer quite yet, until we have more information and statistics on this. I'm definite that in the near future there will be no issues and that Web Components and Polymer will work seamlessly with the bots and search engines.
Resources - Next Steps
For the last video of this course I would like to share some interesting resources I've come across while learning and working with Polymer. The first one of course is the official Polymer JS website. The second site is elements.polymer-project.org where you can find numerous elements made by the Polymer team. Of course, the Polymer Twitter page, the Polymer Slack channel where you can come in content with members of the team and have a more inside look into conversations and ideas about the future of Polymer. The Polycasts series which is a YouTube video series by Rob Donson on Polymer. I find these videos excellent and extremely resourceful. The Polymer Google+ page, the Polymer Starter Kit project, which we already mentioned in the beginning of the course. This is a starter project for your Polymer applications, having a number of problems already addressed such as the routing and your site's architecture. The polymer-dashboard project which is an open source project I'm working on. It is basically a fully working Polymer dashboard so you can use it and build on it if you're thinking of creating a Polymer dashboard. Lastly, you can visit webcomponents.org which is the main site for Web Components. And of course, Pluralsight's course on Web Components created by my friend Cory House. I've already watched his course and it's definitely amazing and I highly recommend it to go even deeper in the technologies we used.
Summary
This is the end of our course on building a web application with Polymer JS and Material Design. I hope you enjoyed watching this course as much as I enjoyed recording it. We created together a full-blown application with the use of Polymer JS stepping on the Material Design principles. While creating this application we went through the basics of Polymer and got accustomed with the principles of Web Components. I can't wait to see what you'll be doing with the Polymer JS library from here on and I would love to hear from anyone who wants to reach me on the discussion panel of the course. Thank you and see you on the next one.
Course author
Bill Stavroulakis
Bill is a Microsoft MVP, Google Developer Expert, a Senior Software Engineer at Software Competitiveness International, and the creator of Dotnetweekly. He has over 7 years of experience in...
Course info
LevelAdvanced
Rating
(101)
My rating
Duration2h 6m
Released14 Dec 2015
Share course