Building <profile-info> Web Component

Let us take a look at an example Web Component. Let's say we have a Web Component called <profile-info>. And the purpose of this Web Component is to show information about an employee. The information could be name, designation, ID number, profile picture, and a card background color to state whether the employee is a full-time employee, a part-time employee, or a contractor.

The HTML structure for this <profile-info> component would look something like this:

<profile-info
name="John Doe"
designation="Frontend Engineer - Marketing"
id-number="PRC-1455"
picture-src="./john-doe.png"
employee-type="ft">
</profile-info>

From the list of attributes, we can see that it needs a name, designation, ID number, picture link, and employee type. This is what it needs to do in terms of functionality. In terms of look and feel, it needs to look like a card with rounded profile picture, along with all the remaining information. And based on the resolution of the screen, it needs be either full-width, or if the screen is that of a mobile device, it should be shown in the form of a card.

Let's do a mobile first approach on the Web Component, and start writing the code:

export default class ProfileInfo extends HTMLElement {
constructor() {

// We are not even going to touch this.
super();

// lets create our shadow root
this.shadowObj = this.attachShadow({mode: 'open'});

// Then lets render the template
this.render();
}

render() {
this.shadowObj.innerHTML = this.getTemplate();
}

getTemplate() {
// Show HTML Here
}
}

This is the most basic part that we have covered in the previous chapters. We are simply creating the component skeleton and making sure that the HTML for the shadow DOM is retrieved from the getTemplate() method.

For the mobile view, the card should look something like this:

The HTML structure would look something like this:

getTemplate() {
return `
<div class="profile-info__container">
<img class="profile-info__picture"
src="${this.getAttribute('picture-src')}" />
<div class="profile-info__text">
<div class="profile-info__name">
${this.getAttribute('name')}
</div>
<div class="profile-info__designation">
${this.getAttribute('designation')}
</div>
<div class="profile-info__id-number">
${this.getAttribute('id-number')}
</div>
</div>
</div>
`;
}

If you take a look at the class names, they are all using BEM patterns.

If you have no idea as to what BEM is, the full form of BEM is Block Element Modifier. It is a methodology of using logical and reusable CSS classes for modular HTML blocks. If you would like to look into it, feel free to look at the following link: http://getbem.com/.

Now, let us take a look at the CSS required to build this card. I am wrapping the CSS inside another method called getStyles() and then I am including it inside the getTemplate() method:

getStyles() {
return `
<style>
:host {
display: block;
font-family: sans-serif;
}
:host(.profile-info__emp-type-ft) {
background-color: #7bb57b;
}
:host(.profile-info__emp-type-pt) {
background-color: #ffc107;
}
:host(.profile-info__emp-type-ct) {
background-color: #03a9f4;
}

.profile-info__container {
display: flex;
color: white;
flex-direction: column;
text-align: center;
}
.profile-info__picture {
border-radius: 50%;
width: 80vw;
height: 80vw;
margin: 10px auto;
}
.profile-info__text {
padding: 10px;
flex: 1;
}
.profile-info__name {
font-size: 28px;
}
.profile-info__designation {
font-size: 22px;
margin-top: 10px;
}
.profile-info__id-number {
margin-top: 10px;
}
</style>
`;
}

And let's add the getStyle() method to the getTemplate() method:

getTemplate() {
return `
...
...
...
${this.getStyles()}
`;
}

If you look inside the getStyles() method, we have these classes: 

  • :host(.profile-info__emp-type-ft)
  • :host(.profile-info__emp-type-pt), and 
  • :host(.profile-info__emp-type-ct).

These change the color of the card on the basis of employee type, that is, full-time, part-time, or contractor, respectively.

But we still have no way to add these classes, so we create a new function called updateCardBackground() that will be responsible for adding the associated class to the Web Component. And then we will call this class inside the render() method:

updateCardBackground() {
this.classList.add(`profile-info__emp-type-${this.getAttribute('employee-type')}`);
}

render() {
this.shadowObj.innerHTML = this.getTemplate();

this.updateCardBackground();
}

It is doing nothing but getting the employee type from the attribute and then adding it to the class name of the host. 

So if the employee is full-time, then the class becomes .profile-info__emp-type-ft; if the employee is part-time, then the class becomes .profile-info__emp-type-pt; and if the employee is a contractor, the class becomes .profile-info__emp-type-ct. Notice how it is grabbing the employee type from the attribute and appending it to the end of the string .profile-info__emp-type-.

Now that we are done with creating the component and styling it, let's add the CSS for larger screens, say tablet and desktop. For the sake of simplicity, we will use the same CSS for desktop and tablet. So, let's add the following CSS to our getStyles() method:

@media screen and (min-width: 650px) {
.profile-info__container {
flex-direction: row;
text-align: left;
}
.profile-info__picture {
width: 100px;
height: 100px;
margin: 10px;
}
}

This makes sure that the Web Component looks like it's from a contact book, the way we see on desktops. And it will show up only when the screen size is more than 650px:

If you are building the Web Component along with this tutorial, try changing the width of the screen.

You can use a similar approach with any of the Web Components and make sure that it looks good when moved from one screen size to another.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.172.132