Skip to content

Commit

Permalink
Merge pull request GeekTrainer#2 from GeekTrainer/cli-components
Browse files Browse the repository at this point in the history
cli components
  • Loading branch information
Christopher Harrison authored Feb 23, 2021
2 parents ce08a41 + d116959 commit fb3cfc0
Show file tree
Hide file tree
Showing 97 changed files with 585 additions and 36,530 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
Let's update a fictitious application for allowing people to book cruises into space. We will add a form to allow someone to book a trip to the moon.

## Exploring the starter code
## Clone the starter repository and explore the code

The starter application already contains the core data model we will use. The `product` has information about the cruise itself, including the list of available `cabins`. The `booking` object is what we will use to store the options the user selects for their reservation. You can see the setup inside **index.js**.
We have provided a starter repository for this module. This will allow us to focus on the concepts we will explore in this module. You will need [Git](https://git-scm.com/) and [Visual Studio Code](https://code.visualstudio.com) installed, and the [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) extension added to Visual Studio Code.

1. Clone the starter repository and open the folder in [Visual Studio Code](https://code.visualstudio.com) by executing the following code

```bash
git clone [INSERT REPOSITORY LINK]
cd [INSERT FOLDER NAME]
code .
```

The starter application already contains the core data model we will use. The `product` has information about the cruise itself, including the list of available `cabins`. The `booking` object is what we will use to store the options the user selects for their reservation. You can see the setup inside **index.js**.

## Create the form

Expand Down Expand Up @@ -65,23 +75,23 @@ We display the list of available cabins by using a `select` element. We want to
<textarea v-model="booking.notes" rows="3"></textarea>
```

We bind the `booking.notes` option to a `textarea`. We set the size by setting the `rows` attribute to *3*.
We bind the `booking.notes` option to a `textarea`. We set the size by setting the `rows` attribute to *3*.

### The todo comment
### The todo comment

You will notice we added a `TODO` comment for ourselves to add in a button. We will see how to create event handlers a little later in this module. We want to make sure we know where to place it when the time comes.
You will notice we added a `TODO` comment for ourselves to add in a button. We will see how to create event handlers a little later in this module. We want to make sure we know where to place it when the time comes.

> ![NOTE]
> `TODO` comments are a great way to make notes in your code of tasks you need to complete in the future.
> ![NOTE]
> `TODO` comments are a great way to make notes in your code of tasks you need to complete in the future.

## Test the results
## Test the results

Let's see our updated page!
Let's see our updated page!
1. Save all files by clicking *File* > *Save all*
1. Ensure *Live Server* is running by pressing *Ctl-Shift-P* (or *Cmd-Shift-P* on a Mac), typing *Live Server* in the command pallet, and selecting *Live Server: Open with Live Server*
1. Open your browser and navigate to **http://localhost:5500**
1. The page now displays
1. Save all files by clicking *File* > *Save all*
1. Launch *Live Server* is running by pressing *Ctl-Shift-P* (or *Cmd-Shift-P* on a Mac), typing *Live Server* in the command pallet, and selecting *Live Server: Open with Live Server*
1. Open your browser and navigate to **http://localhost:5500**
1. The page now displays
![Screenshot of the newly created form](media/form-created.png)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions 4-cli-components/0-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ Prerequisites:
- Familiarity with Vue.js and directives
- [Visual Studio Code](https://code.visualstudio.com)
- [Node.js](https://nodejs.org/en/)

> ![NOTE]
> If you wish to obtain the completed code for this module, you can clone the repository by executing the following in a command or terminal window
>
> ```bash
> git clone [INSERT REPO HERE]
> git clone [INSERT STARTER DIRECTORY HERE]
> code .
> ```
23 changes: 15 additions & 8 deletions 4-cli-components/4-exercise-create-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Let's create the *Host* component.

The snippet creates the `script` element for us with `export default` already created. `export default` allows this component to be loaded by another component in Vue. We will add the needed code into this section.

1. Inside the curly braces (`{ }`) of `export default`, add the following code to name the component, register our data, and add three comments for the future:
1. Inside the curly braces (`{ }`) of `export default`, add the following code to name the component, register our data, and add two comments for the future:

```javascript
name: 'Host',
Expand All @@ -48,8 +48,9 @@ The snippet creates the `script` element for us with `export default` already cr
{ name: 'First', price: 430000 },
]
},
// TODO: Add bookings array

bookings: [
{ name: 'Sample', price: 0 }
]
}
},

Expand All @@ -59,7 +60,7 @@ The snippet creates the `script` element for us with `export default` already cr

```

The `name` field sets the name of the component. `data()` registers the `cruise` object as data for the component. The three `TODO` comments will serve as markers for the future.
The `name` field sets the name of the component. `data()` registers the `cruise` object as data for the component, and `bookings` which we will use later to store a list of cruise bookings. The three `TODO` comments will serve as markers for the future.

> ![NOTE]
> `TODO` comments are a great way to place notes in your code of tasks which need to be completed later.
Expand All @@ -71,21 +72,27 @@ With our data registered, let's add the HTML to the `template` element to displa
1. Inside the `template` element in *Host.vue*, add the following HTML to display the name and description of the cruise, as well as a placeholder for two components we will create later:
```html
<section>
<div class="nav-bar"></div>
<h1>Relecloud Galaxy Tours</h1>
<div>
<h2>{{ product.name }}</h2>
<div>{{ product.description }}</div>
<h2>{{ cruise.name }}</h2>
<div>{{ cruise.description }}</div>
<hr />
<div class="row">
<!-- TODO: Add booking-form -->
<div>
<!-- TODO: Add booking-form -->
<!-- TODO: Add booking-list -->
</div>
<div>
<!-- TODO: Add booking-list -->
</div>
</div>
</div>
</section>
```
## Add the style
Expand Down
119 changes: 78 additions & 41 deletions 4-cli-components/5-props.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,94 @@
HTML elements can display information to the user and allow interaction with the page. We can pass information into the element using attributes, and respond to various events like click. When we create a Vue component we are in essence creating a custom HTML element. As a result, we can implement this same type of functionality through props and custom events.
HTML elements are the building blocks we use to create pages. We can configure their behavior by setting attributes to different values. As highlighted earlier, creating a component is similar to creating a custom HTML tag. As a result, we can pass in information to enhance the reuse of components through props.

## Props as attributes
## Defining props

Props, short for properties, are a collection of different attributes we can add to our components. Their values can be set by the caller in the same fashion as an HTML attribute - a key/value pair. We declare props on a component by setting the `props` property inside the `script` section.
Props, short for properties, are a set of values we can pass into a component. You will typically add props to a component to pass in the values it should display or otherwise change its behavior.

You define props for a component by adding the `props` field inside the `script` element. You can list the names of a components props by listing them in an array:

```html
<!-- UserDisplay component -->
<script>
export default {
name: 'UserDisplay',
props: ['name', 'age']
}
</script>
```

Props are set by the caller of the component using the same syntax as an HTML attribute. Assuming the above component, we can set `name` and `age` like this:

```html
<!-- inside parent component -->
<template>
<user-display :name='Cheryl' :age='28'></user-display>
</template>
<script>
import UserDisplay from './UserDisplay.vue';
export default {
components: {
UserDisplay
}
}
</script>
```

> ![NOTE]
> The component named `UserDisplay` will be converted into the kebab-cased `user-display` by Vue.js. Also, the `:` in front of each name indicates this is a Vue.js property we are setting.
## Restricting types

By listing them as part of an array, the caller can pass in values of any type. This can be appropriate for basic applications, but you will often want to indicate what data types you are expecting for each prop.

We can provide more robust information about the props we are expecting by defining a schema. If you want to indicate `name` should be a string and `age` a number, you can define your props schema like the following:

```html
<!-- UserDisplay component script -->
<script>
export default {
name: 'UserDisplay',
props: ['lastName', 'firstName']
props: {
name: String,
age: Number
}
}
</script>
```

In the above example, we can set the values for the properties `lastName` and `firstName` by adding attributes to the `user-display` element the component creates. Notice the names will be converted into kebab-case, just like the name of the component itself.
Notice how we are creating a props object with the types for `name` and `age`. This component will now only accept the specified data types. We can still set them as before:

```html
<user-display first-name="Cheryl" last-name="Smith"></user-display>
<!-- inside parent component -->
<user-display :name='Cheryl' :age='28'></user-display>
```

We can also create more robust props by creating a template for the object, similar to how you might declare a schema. If we had a `user` object with `firstName` and `lastName` properties of type `String`, we can register it in our component as follows:
## Complex objects

When working with Vue you will typically work with objects rather than individual values. Fortunately you can declare more complex structures with props as well.

If we are using a `User` object with the properties of `name` and `age`, we can declare this as a full construct in our props:

```html
<!-- UserDisplay component script -->
<script>
export default {
user: {
firstName: String,
lastName: String
name: 'UserDisplay',
props: {
user: {
name: String,
age: Number
}
}
props: ['lastName', 'firstName']
}
</script>
```

We can then use the component with the following:
We can set the value using the attribute as we did before. In addition, we can pass in dynamic data as well by specifying the name of the object we wish to use. In the example below we have a piece of data named `user`, which is passed using the same syntax as static values.

```html
<!-- parent component -->
<template>
<user-display user="user"></user-display>
<user-display :user="user"></user-display>
</template>

<script>
Expand All @@ -55,44 +106,30 @@ export default {
UserDisplay
}
}
```
> ![IMPORTANT]
> Props are designed to be read-only for a component. If you need to modify values you can use `data()`.
## Events
HTML elements can raise events based on user interaction. Components allow us to do the same thing by emitting events. When creating the component you register any events your component may emit by listing them in the `emits` field in the `script`.
```html
<!-- inside the component's vue file -->
<script>
export default {
// normal component fields
emits: ['saveUser']
}
</script>
```

Emitting an event is done by using the `emit` function. You can call this function directly inside an event handler using the normal Vue syntax:
## Using props inside a component

Inside a component, props can be read in the same way you would read data. The full `UserDisplay` component might look like this:

```html
<!-- inside the component's vue file -->
<template>
<!-- the rest of the template -->
<button @click="emit('saveUser')">Save user</button>
<div>Name: {{ user.name }}</div>
<div>Age: {{ user.age }}</div>
</template>
```
You can also emit an event from inside a method by using `this.$emit`.
```html
<!-- inside the component's vue file -->
<script>
export default {
// normal component fields
emits: ['saveUser']
name: 'UserDisplay',
props: {
user: {
name: String,
age: Number
}
}
}
</script>
```

> ![IMPORTANT]
> Unlike stateful data, values passed via props are a one-way binding. If changes are made to a prop those updates do *not* bubble back to the parent.
Loading

0 comments on commit fb3cfc0

Please sign in to comment.