This lab corresponds to the section Component Basics of the VueSchool course Vue.js Components Fundamentals
This repository contains only the example codes for
- The click counter (video Introduction to Components) and
- plan-picker
examples used inside the initial section of the tutorial Component Basics.
The goal is to write a simple component <click-counter>
that can be called like that:
<div id="app">
<h1>Vue.js Components Fundamentals</h1>
<click-counter></click-counter>
<click-counter></click-counter>
<click-counter></click-counter>
<click-counter></click-counter>
</div>
so that when you click in the input the counter shown is increased. The code above has to work as shown here: https://crguezl.github.io/vuejs-components-basics-plan-picker-component/click-counter/solution.html
Watch the videos
And write your code inside the empty files index.html
and app.js
.
Files click-counter/solution.html and click-counter/solution-app.js contain the final solution.
├── app.js
├── index.html
├── solution-app.js
└── solution.html
-
All along, use as many emmet expressions as you can to speed up the edition
-
Set the initial HTML and load Vue from the CDN
-
Inside the app create the Vue app attached to the corresponding div element
-
Create a component
click-counter
usingVue.component
- Add the
data
function that returns the object with the data. - Set the
count
- In the template add the
v-on
to increase the counter each time the button is clicked
- Add the
-
Add in the
app
div of the HTML the component just created -
Insert new instances of the component in the HTML
-
Move the template from the
app.js
to the HTML using ascript
tag -
Instead of
<script type= 'text/x-template' ...>
try also to use the<template>
HTML tag. Does it works? -
Add a second element, a paragraph
the count is
to theclick-counter
component -
Wrap the two elements in a
<div>
-
Move all the code from
app.js
to the HTMLindex.html
-
Add a
prop
with nameclick-title
to theclick-counter
component so that instead of the fixed"the count is"
, the parent component can specify the prefix paragraph:<click-counter click-title="The first counter is:"></click-counter> <click-counter click-title="The second counter is:"></click-counter> <click-counter click-title="The Third counter is:"></click-counter>
Read the section Prop Casing (camelCase vs kebab-case) of the Annotated Reading of the Essentials Section of the Vue.js Guide
In this exercise you have to start from a HTML file that contains repeated <div class="plan">
like
<div class="plans">
<div class="plan">
<div class="description">
<span class="title">
The Single
</span>
</div>
</div>
<div class="plan">
<div class="description">
<span class="title">
The Addict
</span>
</div>
</div>
...
</div>
and you have to factorize the code introducing a Vue.js component <plan>
Watch the videos
- Reusable Components with Props 6:46
- Nested Components 1:50
- Global vs Local Components 3:11
- Communication Between Components with Custom Events 7:24
Leave your solution inside the files index.html
and app.js
.
Here is the structure of the folder:
├── coffee.jpg
├── index.html
├── logo.png
├── solution-app.js
├── solution.html
└── style.css
Files plan-picker/solution.html and plan-picker/solution-app.js contain the final solution.
See the solution working at https://crguezl.github.io/vuejs-components-basics-plan-picker-component/plan-picker/solution.html
-
Use a minimum number of emmet expressions to generate complete the initial
index.html
to have it as at the beginning of the video Reusable Components with Props. The structure to replicate three or four times has to follow this pattern:<div class="plans"> <div class="plan"> <div class="description"> <span class="title"> The Single </span> </div> </div> ... more like the one above </div>
- Here is a solution
-
Load Vue from the CDN and add the main app
-
Create the
plan
component that encapsulates the template above -
Add it the
prop
with thename
, interpolate it inside the component template and update the calls in the HTML accordingly for all the repetitions -
Add to the Vue app data the
plans
array of Strings with the names of the plans -
Substitute the repetitions of the
<plan>
component inside the HTML for av-for
loop -
Specify that the
prop
name
has to be of typeString
and isrequired
Nested Components Video
- Create a component with name
<plan-picker>
to encapsulate the.plans
div - Create the template for the component and move the
plans
array into the component
- Make the
plan
component local to theplan-picker
component- Check that a local component can not be used out of its scope
- Make the
plan-picker
component local to the root component- Register first the component with the name
planPicker
and try to use it. What happens? - Change the name to
plan-picker
- Register first the component with the name
We want to add the capability to select a plan. See how the solution works when you click in one of the plans. We want to reproduce this behavior,
-
Add a boolean variable
selected
to theplan
component -
Add a
select
method to theplan
component to set the component as selected -
Add the code so that when a user clicks on the root element of the
plan
component template theselect
method is called- See Event Handling and Component Custom Events in the Vue.js Guide
- What happens if you add the code for the click on an element inside the
plan
component?
-
Using the object syntax for
v-bind
add a classactive-plan
when aplan
component is selected so that the background color of the button changes when selected, since thestyle.css
contains the following:.plans .active-plan { border-color: #352001; background-image: linear-gradient(to bottom right, white, #8F4401); }
See Class and Style Bindings in the Vue.js Guide
-
Verify that, unfortunately, the solution given permits several plans to be selected
-
We need to let the component communicate to its parent when the user has clicked on it. Make the
plan
component to$emit
an event with nameselect
and payload thename
of the plan- Read the notes on the api of vm.$emit( eventName, […args] )
-
Check in the event tab of the Vue DevTools the presence of the events generated when you click
-
Inside the
plan-picker
component template set the triggering of a methodselectPlan
to fire when theselect
event is emitted. -
Inside the
plan-picker
component add a data attributeselectedPlan
to store the plan that was selected by the user -
Add also the code for the
selectPlan
method -
The idea is now that the parent
plan-picker
component will send the selected plan as a property to the children components.Go back to the
plan
component and remove theselected
data property (it is no longer need, since the parent component now knows which plan has been selected) -
Add a property
selectedPlan
to theplan
component (that will be passed by the parent) -
Add a computed property
isSelected
to theplan
component that istrue
when the plan is the one selected -
In the template of the
plan
component conditionally bind the classactive-plan
to the.plan
div if the plan is selected -
Inside the
plan-picker-template
pass the propertyselectedPlan
to the children.- Be carefull that HTML attributes are case insensitive but the name of the
plan
attribute we choose inside the JavaScript code wasselectedPlan
(CamelCase) and so to writev-bind:selectedPlan="..."
is not going to work. You have to use the equivalent kebab-case string
- Be carefull that HTML attributes are case insensitive but the name of the
After this lab, you'll be familiar with:
- The idea behind components and how Vue.js components work
- Component's template, and couple of ways to define your template
- Communication between components with props and custom events
- What is the difference between global and local component registration