Description
Objective:
For this final assignment, students will work with an existing Angular application (ie: Assignment 5) and update
it to allow users to edit data as well as to practice building and deploying their App to the cloud (Heroku).
Note: This assignment relies on the successful completion of Assignment 5. If you require a fresh copy of
Assignment 5, please email your Professor.
Specification:
For our updated Assignment 5 application (now Assignment 6) we will use our knowledge of Template Driven
Angular Forms to allow users to edit employee / position information as well as add some search/filtering to
our Employees table to make it more useable. Lastly, we will deploy it on Heroku.
Getting Started:
To begin this assignment, we will first need to make a copy of or current Assignment 5 and open it in Visual
Studio Code. Once it is open, we can proceed to add new methods to our Employee & Position
services (Part 1)
NOTE: For Assignment 5, we didn’t address the issue of the background slider images, ie: the console errors
that look like:
images/slider/bg3.jpg Failed to load resource: the server responded with a status of 404 (Not Found)
To fix these errors, simply open your home.component.html file and modify the 3 image paths (bg1.jpg,
bg2.jpg & bg3.jpg) from: images/slider/… to /assets/images/slider/… This should give you your slider
backgrounds back:
Part 1 – New Functionality for Editing Employees / Positions
Step 1 – Updating EmployeeService & PositionService
For this assignment, we will enable users to edit existing employees & services. To enable this functionality,
we must add some additional properites & methods to our EmployeeService & PositionService:
EmployeeService (employee.service.ts)
Before we can begin to update our EmployeeService, we must define a new class: EmployeeRaw in its own file
(employeeRaw.ts) within the “data” folder. The EmployeeRaw class must have the following properties /
types:
Property Type
_id string
FirstName string
LastName string
AddressStreet string
AddressState string
AddressCity string
AddressZip string
PhoneNum string
Extension number
Position string
HireDate string
SalaryBonus number
__v number
Next, we must import our new EmployeeRaw class in our EmployeeService. This will allow us to create the
following additional 2 methods:
• saveEmployee(employee: EmployeeRaw)
This method must make a “put” request (using the HTTPClient module) to your Teams API running on heroku
with the path: “/employee/id” (where “id” matches the employee’s “_id” property). It will return an Observable
of type any, ie: Observable
ie:
o return this.http.put
• getEmployee(id)
This method must make a “get” request (using the HTTPClient module) to your Teams API running on heroku
with the path: “/employee-raw/id” (where “id” matches the “id” parameter to the function). It will return an
Observable of type EmployeeRaw[], ie: Observable
one element (containing the “raw” Employee object)
PositionService (position.service.ts)
This service needs to create the following additional 2 methods:
• savePosition(position: Position)
This method must make a “put” request (using the HTTPClient module) to your Teams API running on heroku
with the path: “/position/id” (where “id” matches the position’s “_id” property). It will return an Observable of
type any, ie: Observable
o return this.http.put
• getPosition(id)
This method must make a “get” request (using the HTTPClient module) to your Teams API running on heroku
with the path: “/position/id” (where “id” matches the “id” parameter to the function). It will return an
Observable of type Position[], ie: Observable
(containing the Position object)
Step 2 – Creating New Components (EmployeeComponent & PositionComponent)
Now that we have our new service methods to fetch a specific employee / position, we can create the
components that will enable us to edit existing employees and positions. This involves creating two new
components: EmployeeComponent & PositionComponent.
Use the @angular/cli (ie: ng generate) to create these components now.
Once these components are created, add the following properties / methods according to the specifications
outlined below:
EmployeeComponent (employee.component.css)
To keep the look and feel of our app consistent, we must add the following css:
• .center{ margin-top:40px; }
EmployeeComponent (employee.component.ts)
Properties:
• paramSubscription ( type any)
• employeeSubscription ( type any)
• getPositionsSubcription ( type any )
• saveEmployeeSubscription ( type any)
• employee ( type EmployeeRaw )
• positions( type Position[] )
• successMessage ( set to false )
• failMessage (set to false)
Methods:
• constructor()
In this method, we must inject the following Services:
o EmployeeService from employee.service
o ActivatedRoute from @angular/router
o PositionService from position.service
• ngOnInit()
In this method, we will use Injected services / modules to perform the following tasks:
o Determine what the value of the _id variable is in the Route parameter using the ActivatedRoute service
(Note: a reference to the subscription should be stored using “paramSubscription” so that it can be
disposed of later)
o Use the value of _id to populate the “employee” property using the EmployeeService service (Note: a
reference to the subscription should be stored using “employeeSubscription” so that it can be disposed
of later)
o populate the “positions” property using the PositionService service (Note: a reference to the
subscription should be stored using “getPositionsSub” so that it can be disposed of later)
• onSubmit()
In this method, we will use Injected services / modules to perform the following tasks:
o Persist (“save”) the “employee” property using the EmployeeService service (Note: a reference to the
subscription should be stored using “saveEmployeeSubscription” so that it can be disposed of later)
o If the subscription output the data successfully (ie, in the first callback):
▪ Set the value of the successMessage property to true
▪ Using the setTimeout() method, automatically set the successMessage property to false after
2500 ms
o If the subscription failed to output the data (ie, in the second callback):
▪ Set the value of the failMessage property to true
▪ Using the setTimeout() method, automatically set the failMessage property to false after 2500
ms
• ngOnDestroy
In this method we call the “unsubscribe()” methods on any saved subscriptions within the component (ie:
paramSubscription, etc) – Note: we must make sure they are not “undefined” before we call “unsubscribe()”
PositionComponent (position.component.css)
To keep the look and feel of our app consistent, we must add the following css:
• .center{ margin-top:40px; }
PositionComponent (position.component.ts)
Properties:
• paramSubscription ( type any)
• positionSubscription ( type any)
• savePositionSubscription (type any )
• position( type Position )
• successMessage ( set to false )
• failMessage (set to false)
Methods:
• constructor()
In this method, we must inject the following Services:
o PositionService from position.service
o ActivatedRoute from @angular/router
• ngOnInit()
In this method, we will use Injected services / modules to perform the following tasks:
o Determine what the value of the _id variable is in the Route parameter using the ActivatedRoute service
(Note: a reference to the subscription should be stored using “paramSubscription” so that it can be
disposed of later)
o Use the value of _id to populate the “position” property using the PositionService service (Note: a
reference to the subscription should be stored using “positionSubscription” so that it can be disposed of
later)
• onSubmit()
In this method, we will use Injected services / modules to perform the following tasks:
o Persist (“save”) the “position” property using the PositionService service (Note: a reference to the
subscription should be stored using “savePositionSubscription” so that it can be disposed of later)
o If the subscription output the data successfully (ie, in the first callback):
▪ Set the value of the successMessage property to true
▪ Using the setTimeout() method, automatically set the successMessage property to false after
2500 ms
o If the subscription failed to output the data (ie, in the second callback):
▪ Set the value of the failMessage property to true
▪ Using the setTimeout() method, automatically set the failMessage property to false after 2500
ms
• ngOnDestroy
In this method we call the “unsubscribe()” methods on any saved subscriptions within the component (ie:
paramSubscription, etc) – Note: we must make sure they are not “undefined” before we call “unsubscribe()”
Step 2 – Creating Routes for the Employees / Positions Components
Now that we have our new components in place and capable of reading route parameters, we must update
app-routing-module.ts and our existing EmployeesComponent & PositionsComponent files so that we can
successfully navigate to the new routes for a specific employee / position.
app-routing-module.ts
Add the following routes:
Route Path Component / Options
employee/:_id EmployeeComponent
position/:_id PositionComponent
EmployeesComponent (employees.component.ts)
Our goal here is to allow users to click on a specific employee row, which will cause them to be sent to the
corresponding employee view (using the /employee/:_id route)
To enable this, we must modify the EmployeesComponent according to the following specification
• Inject Router from @angular/router in the constructor parameters as “router”
• Add the method: routeEmployee(id: string)
o In this method, we use the Injected router instance to “navigate” the to the /employee/id route (where
id is the parameter passed to the function) – HINT: see this.router.navigate in the “Angular Services
Intro” notes
EmployeesComponent (employees.component.html)
With our new “routeEmployee(id)” method in place, we can now update our EmployeesComponent template
(employees.component.html) to invoke the method by binding a “click” event to the same
has our *ngFor directive. This click event will invoke the routeEmployee() method and pass in the value of the
current employee’s _id value, ie “routeEmployee(employee._id)”
By adding the click binding to the repeated
have the correct event, and invoke the routeEmployee method for the matching employee _id value for that
row in the table.
PositionsComponent (positions.component.ts)
Similar to EmployeesComponent, our goal is to allow users to click on a specific position row, which will cause
them to be sent to the corresponding position view (using the /position/:_id route)
To enable this, we must modify the PositionsComponent according to the following specification
• Inject Router from @angular/router in the constructor parameters as “router”
• Add the method: routePosition(id: string)
o In this method, we use the Injected router instance to “navigate” the to the /position/id route (where id
is the parameter passed to the function) – HINT: see this.router.navigate in the “Angular Services Intro”
notes
PositionsComponent (employees.component.html)
Again, this is the same process as our EmployeesComponent template, ie: we must update our
PositionsComponent template (positions.component.html) to invoke the routePosition method by binding a
“click” event to the same
routePosition() method and pass in the value of the current positions’s _id value, ie
“routePosition(position._id)”
Step 3 – Creating the Templates / Forms (EmployeeComponent & PositionComponent)
With our Component logic in place, we can now concentrate on creating the templates for our Employee &
Position Components. However, before we start, we need to update our assets/main.css file, so that our
forms render more clearly in the application:
assets/main.css
• in the .form-group . form-control style (line 736), change the border-color property from: #f2f2f2 to #d2d2d2
• At the bottom of the file, below all the other styles, add:
o .table-hover tr{ cursor: pointer; }
With this complete, we can focus on adding our template content / forms to our new Employee & Position
Components.
IMPORTANT NOTE: Before we can use Forms in Angular, we must:
• Import FormsModule from @angular/forms in our app.module.ts
• Add FormsModule to the imports: [] array in app.module.ts
EmployeeComponent (employee.component.html)
To get you started, we have provided some boilerplate, static HTML that can be used to kick start the
template:
https://scs.senecac.on.ca/~patrick.crawford/shared/winter-2019/web422/A6/employee.component.html.txt
Once you have copied the contents of the above .txt file into your employee.component.html file, you should
have almost all the fields you will need to update an existing employee:
• With this HTML in place, we have a view that features a blank form and placeholder data. We need to update
this view to use real data from the component (ie: employee and positions) for all form fields and any other
placeholder locations (ie: in the “alert” elements at the bottom and the
…
element at the top).
• Regarding the form fields, remember to:
o Add (ngSubmit)=”onSubmit()” to your