Lessons: 67Length: 8.9 hours

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

3.7 Models

We'll spend most of the course looking at the view and controller parts of Angular's MVC (model-view-controller) architecture, but first we should understand how models work. In this lesson we'll do just that.

1.Introduction
6 lessons, 42:00

1.1
Introduction
00:48

1.2
Get Started With Angular-CLI
11:09

1.3
Developing With Angular-CLI
13:17

1.4
TypeScript vs. JavaScript
06:54

1.5
Angular Modules From the CLI
04:31

1.6
CLI Options
05:21

2.Get Started With Angular
7 lessons, 42:38

2.1
Bootstrapping the Application
04:30

2.2
The Application Module
04:15

2.3
The Application Component
08:06

2.4
Component Styling
03:06

2.5
Global Styling
05:11

2.6
Creating a Component With the CLI
09:34

2.7
Creating a Service With the CLI
07:56

3.Core Concepts
7 lessons, 55:20

3.1
Component Trees
06:20

3.2
Dependency Injection
06:52

3.3
Content Projection
05:38

3.4
Component and Directive Lifecycle Methods
06:31

3.5
Component-Only Lifecycle Methods
05:28

3.6
Decorators
07:36

3.7
Models
16:55

4.Template Deep Dive
11 lessons, 1:10:56

4.1
Basic Data Binding With Interpolation
05:35

4.2
Property Bindings
07:07

4.3
Attribute Bindings
03:29

4.4
Event Bindings
08:16

4.5
Class and Style Bindings
05:44

4.6
The `NgClass` and `NgStyle` Directives
05:04

4.7
The `*ngIf` Directive
04:41

4.8
The `*ngFor` Directive
09:29

4.9
Inputs
05:33

4.10
Using Pipes in a Template
07:31

4.11
Using Pipes in a Class
08:27

5.Forms
10 lessons, 1:45:41

5.1
Handling User Input With Template Reference Variables
07:06

5.2
Template-Driven Forms
11:10

5.3
Template-Driven Forms: Validation and Submission
14:00

5.4
Reactive Forms
11:26

5.5
Using a `FormBuilder`
08:01

5.6
Reactive Validation With Built-in Validators
14:53

5.7
Creating Custom Validators for Template-Driven Forms
12:18

5.8
Creating Custom Validators for Reactive Forms
08:26

5.9
Observing Form State Changes
12:40

5.10
Working With the `@HostListener` Decorator
05:41

6.Routing
9 lessons, 1:15:10

6.1
Defining and Configuring Routes
07:53

6.2
Rendering Components With Router Outlets
10:14

6.3
Using Router Links for Navigation
05:25

6.4
Navigating Routes Using the Router
06:24

6.5
Determining the Active Route Using an Activated Route
07:16

6.6
Working With Route Parameters
10:42

6.7
Using Route Guards
07:36

6.8
Observing Router Events
10:55

6.9
Adding Child Routes
08:45

7.Using the HTTP Client
5 lessons, 56:24

7.1
Sending an HTTP Request
10:52

7.2
Handling an HTTP Response
11:22

7.3
Setting Request Headers
12:33

7.4
Intercepting Requests
09:04

7.5
Finishing the Example Application
12:33

8.Testing
10 lessons, 1:23:27

8.1
Service Unit Test Preparation
10:45

8.2
Unit Testing Services
13:24

8.3
Component Unit Test Preparation
12:35

8.4
Unit Testing Components
07:27

8.5
Unit Testing Component Templates
06:58

8.6
Unit Testing Pipes
04:41

8.7
Unit Testing Directives
04:56

8.8
Unit Testing Validators
04:48

8.9
Unit Testing Observables
11:37

8.10
Unit Testing HTTP Interceptors
06:16

9.Building for Production
1 lesson, 03:40

9.1
Building for Production
03:40

10.Conclusion
1 lesson, 01:32

10.1
Conclusion
01:32


3.7 Models

Hi folks. In this lesson, we're going to take a quick look at models. Now, Angular doesn't have a built-in definition of the term model. There's no app model decorator, or anything like that. And just to clarify, I mean model in the sense of an MVC model. So an entity that encapsulates the data used by your application. Even though Angular 2 and above doesn't have a formal definition of a controller anymore, the components class can be seen as a controller of sorts. And Angular can still be loosely described as an MVC framework. So most applications are going to need some objects, which contain the data for the application, and maybe some behavior or logic as well. And the example application that we're building will, too. So that's what we're going to look at in this lesson. The example application that we're building is a card game. So one object that we're definitely going to need is a card, which represents a playing card. So let's add a card model first of all. We can create a new folder for our models. They're going to be very generic, rather than being part of any single component or feature. So let's call the folder _models This will then sit right up at the top of the app folder with our generic_services folder. So inside this new folder, let's create a new typescript file called card.ts. So this will be a very simple class, And inside the constructor we can specify some public properties. So cards have three simple string properties, colored suit and name, and finally a value property which will be a number. The constructor accepts these as arguments and because we use the public key word, typescript will automatically add the values past into the constructors as properties. We don't have to do this manually and type the constructor body. Another object that we're going to need is a player. So let's add a player model as well. We can add a new file cool player.ts to the _models folder. And again this will be simple class, So we specify two public properties of the class, a score and a hand property. We aren't providing any type information here, and there's actually an error because I used a colon and that should be an equals sign. So going back to what I was about to say then, we're not providing any typing information here, we are initializing the values, and that's why we don't need to provide typing information. We don't need to tell typescript that score will be a number, because we're initializing it with a numeric value. So the type for this property is implied. Typescript already knows that it's gonna be a number. And the same with the hand property, it's an array, we're initializing it with an array, so typescript will understand that this property will be of the array type. So now let's add a constructor, And the only thing that will get passed to the constructor is the name of the player and we use the public keyword again to get typescript to add this as a public property. And we do specify the type here because we're not actually going to initialize the value. That will happen when we new up instances of this player class. There's one more model that we'll need, and that will be a deck. So this will be used to create the deck of cards and provide some behavior in the form of shuffling and and dealing the cards. This will bring together the player and card objects, and is a much bigger model than the previous two models. So let's create a new file for this one. We will need to import some things for this model. So we'll need to import the card, the player, and the constant service. We'll also need a function does nothing, commonly known as a noop or noop. So this is an error function that simply returns undefined. We could probably actually put that into the constant service because it's the kind of thing that we do use all over an application. But I'm just gonna leave that as a local variable within this file for now. So now we can have the deck class itself. So the type information that we specified here is quite different than any that we've used before. So what we are staying here is that the cards property will be an array of card objects. Now let's add the constructor. So the constructor for this class accepts a single parameter called aces high which will be a Boolean. And we actually want to initialize our card array as an empty array, and we can do that where we specify the property. So inside the constructor, we'll first need to create a new instance of the constants service. Even though it's an Angular service, it's still basically a class, so we can just create an instance of it using new as we would a regular class. Next, we can build the deck of cards. We'll need 52 cards in specific groups of colors and cards. And we'll use a loop based on the suits' constant. Let's just open up the constants service. So you can see that we've got a number of things in here. We've got an array for the colors, so those will be the different colors. Cards can either be black or red. We've also got a suits array. There are typically four suits of cards, spades, hearts, diamonds, and clubs. We then have an array for the face cards, so these are special cards. They aren't just numbers, they normally have pictures on them, ace, jack, queen, and king. And then lastly we have all of the regular cards, these are known as PIP cards and they typically have values from one to ten. So these are some of the things that we're gonna be making use of as we build our deck. The first thing that we're gonna use is the array of suits. So we've used the forEach method on the suits array. And each time the callback function gets invoked, it will be passed the current suit and the suit's index. Inside this function, we first need to check whether aces are high, because this affects the value of the card. By default, aces are low in Blackjack, and so worth one points. If they are high, however, they are worth 11. So we need to splice the value 1 out from the start of the PIPS array and replace it with the value 11 instead. If aces aren't high, we just invoke out noop function. Noops are super useful for ternary statements like this. To create the individual cards within each suits, we can use the PIPS array from the constants. We need another loop for this part and we need to handle the face cards, ace, jack, queen and king as well as regular number cards. Inside the inner forEach, we can first define a variable called name. If the current value is 1 or 11, we set the name variable to faces 0 which will be ace. So we can use a similar ternary and noop expression here, just like before. So now if the value of the card is equal to 1 or 11, we give it the first item from the faces array, which will be ace, and otherwise, we just invoke our noop function. So at this point, if the value of the card is equal to ten, then it's one of the other face cards. So we can set the card name to either jack, queen, or king depending on which card it is. So we're using the faceCount variable to iterate through the faces array, to make sure that each card with a value of ten gets given the correct name. So there will be a jack, a queen, and a king. Once we've set the name to king, which will be CONSTS.FACES3, then we need to reset the faceCount variable, and that will then get reused for the next suit. So we also need to determine the color of the card, and that will be either red or black. So if the suit index is equal to either 0 or 3, the color will be black, otherwise, the color will be red. And last of all, we can create the new card. We want to push that into the cards array at the point of creation. So this should results in a deck of 52 cards being created. The deck will also need methods to shuffle and deal the cards, so let's add these quickly as well. And it looks like I'm missing a closing parenthesis to start that in there. So let's add the shuffle method first of all. So we need a temporary copy of the cards array so we can use the slice method to create a copy of that array and that won't affect the original array then So in order to shuffle the deck of cards, we use a for loop here. And then inside the for loop, we use destructuring assignment to randomly shuffle the order of the cards based on the counter variables from the for loop and a random number. So now we want to add a method that will deal cards. So we've got some underlining here, and I think we can ignore that in this case. So let's move on to add the deal method. So this method will take an array of players that the cards will be dealt to and the number of cards to deal to each player as arguments. So for each player, we pop one of the cards off of the cards array which belongs to the deck class, and we do this to make sure that two players don't get dealt the same card. We can then push that new card into the player's hand, and update the players score at the same time. So that should be the deck model in its entirety. Just in case you're interested, the shuffle method uses a Durstenfeld shuffle, which is a computer optimized version of the classic Fisher-Yates sorting algorithm. So let's just test our new models out quickly, and we can do that using the home component. So let's import the deck. And let's just add an ngOnInit. And inside the OnInit, let's initialize a new deck, and see if we can log into the console. So we'll just keep aces low for the time being. And let's check it out in the browser. And we can see that we have our deck here, and we have an array of 52 cards. So we have all of the spades, we've got the ace, and the jack, queen and king. Then we have all of the hearts, which are red, all of the diamonds which are red, and all of the clubs which are black, perfect! And if we really wanted to make sure that everything was working properly, we could also test the shuffling and the dealing. We'll need to bring in the player model for this part. What we've done so far should create two new players, one called Dealer, one called Dan. And then it should deal two cards to each of the players. So let's take a look at one of the players, and let's check things out in the browsers console. So we can see that the player has been created correctly. It looks like I've got quite a good score, it's a shame I'm not actually playing the game yet. And I've got two cards in my hand, which sounds about right. And one is a spade and one is a heart and I've got a king and a jack. So that looks like the shuffling and the dealing worked as expected. So in this lesson, we created some models that will be used by the example application. These are mostly quite simple models. Two of them have no methods and just a couple properties each. One of them, the deck model was quite a bit more complex and had a lot of initialization that happened in the constructor as well as a couple of methods. Thanks for watching.

Back to the top