Angular Project Content:
- Part 1 – Setting up the project
- Part 2 – Routing & Customisation
- Part 3 – Populate UI with Data (this one)
Populate Cards
1. Open my-dashboard.component.css and replace all the content with the code below:
.main-container { padding: 10px; } .grid-container { display: inherit; margin: 20px; } .flex-container { display: flex; flex-wrap: wrap; flex-shrink: 1; flex-basis: auto; } .dashboard-card { left: 10px; right: 10px; margin-bottom: 2%; flex-shrink: 1; flex-grow: 1; } .more-button { position: absolute; top: 5px; right: 10px; } .dashboard-card-content { text-align: left; } .example-header-image { background-size: cover; }
2. Open my-dashboard.component.ts and populate cards.
/** Empty Cards Array */ public cards= [];
for (var i = 1; i < randomPics.length; i++) { for (let picture of randomPics) { this.cards.push({ id: i++, pic: picture, likes: 0 }); } }
3. Open my-dashboard.component.html and replace all the contents with the code below:
<div class="grid-container"> <mat-grid-list cols="2" style="padding: 5%"> <mat-card class="dashboard-card" *ngFor="let card of cards"> <mat-card-header> <!-- Static avatar image for card--> <img mat-card-avatar class="example-header-image" src="https://material.angular.io/assets/img/examples/shiba1.jpg"> <mat-card-title>Dogy {{card.id}}</mat-card-title> <mat-card-subtitle>Breed: <i>{{selectedValue}}</i> </mat-card-subtitle> <button mat-icon-button class="more-button" [matMenuTriggerFor]="menu" aria-label="Toggle menu"> <mat-icon>more_vert</mat-icon> </button> <mat-menu #menu="matMenu" xPosition="before"> <button mat-menu-item>Expand</button> <button mat-menu-item (click)="closeCard(card)">Remove</button> </mat-menu> </mat-card-header> <img mat-card-image src="{{card.img_link}}" alt="Photo of a dog"> <!-- Static content of card--> <mat-card-content class="dashboard-card-content"> <p> The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan. A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally bred for hunting. </p> </mat-card-content> <mat-card-actions> <button mat-button (click)="count(card)"> <b>{{card.likes}} </b> <i class="material-icons"> favorite_border </i> </button> <button mat-button>SHARE</button> </mat-card-actions> </mat-card> </mat-grid-list> </div>
Populate Cards – Selected breed
1. Add two new functions in the dogs.service.ts file. Your file should look like the one below:
The first function called getAllBreeds() will get you a list of all available breeds, while the second function, getRandomPicsForBreed() takes one parameter which is the breed you selected and gets you five random images for that dog breed.
2. Open my-dashboard.component.ts and populate the list of dog breeds.
2.1. Declare allBreeds array before the constructor:
2.2. Create new function called getAllBreeds():
Given the nature of the data returned by the API, I found it easier to stringify then parse the data. Then, using Object.keys() I return an array containing all the breeds. If you save this file and check the console in the web browser, you should see the below output:
3. Allow user to select breed from UI.
3.1. Open my-dashboard.html and add the following code at the top of the page.
<div class="main-container"> <div class="row"> <div class="col-sm-4"> <form> <mat-form-field> <mat-select placeholder="Select breed" [(ngModel)]="selectedValue" name="breed" (ngModelChange)="selectedBreed($event)"> <mat-option *ngFor="let breed of allBreeds" [value]="breed"> {{breed}} </mat-option> </mat-select> </mat-form-field> </form> </div> <div class="col-sm-8" align="right"> <button mat-flat-button color="primary" (click)="getRandomPics()" align="center">Random Refresh</button> </div> </div> </div> <mat-divider></mat-divider>
This creates a drop-down that contains all the dog breeds. When a breed is selected, a function that doesn’t yet exist is called. That function will get new random pictures for the selected breed. There is also a button on the right side of the screen. When this button is pressed, the getRandomPics() function is called again and refreshes the cards on the page.
Your button and drop-down will not be aligned correctly, add the following line of code to your index.html file, in the head section.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
3.2. Open app.modules.ts and add the following imports:
These modules are required for the web page to work and render correctly.
If you save the page now, the dropdown and new button should show up. The button will work fine, but when a breed is selected from the drop-down, an error will show up in the console. That’s because the function that gets called doesn’t exist. On the other hand, the Breed gets set on all of the cards now. That’s because we are using a ngModel and use the same variable on line 29, in the <mat-card-subtitle> element.
3.3. Get images for the selected breed.
First, let’s create a simple function called selectedBreed. All this function has to do is to call a different function that will populate the cards.
For now, let’s just console log the selectedBreed param and see if it works as we expect it. What we select from the drop down, it should be displayed in the console.
As you can see from above, whenever we select a breed, the name of the breed is displayed in the console. Now is time to call the function that will get the dog pictures based on the breed.
Next, create the function gets all the pictures of dogs based on the breed:
Make sure that line 75 is uncommented and save the file. Check it in the browser. The page should show cards based on the selected breed.
Count number of likes
1. Add the following function to my-dashboard.component.ts
public count(card:any) { for (var x in this.cards) { if (this.cards[x] === card) { this.cards[x].likes = this.cards[x].likes + 1; console.log(this.cards[x]); } } }
This for loop is going through all the cards and if any of the cards matches the card passed in the function, then it will increment the number of likes by one.
The console log will show you the card object every time the like button is clicked. Feel free to take out the console.log().
Conclusion
Building this app is a lot simpler than it looks. There is plenty of room for improvements, like adding error validation, allowing users to add their own photos or add unit tests, but the purpose of this tutorial was just to show easy it is to build an application using Angular 6 and Angular Material. Please make sure you read and understand the Angular Documentation properly before trying to work on very advanced projects. It will only make your life easier.