Appearance
Lesson 5 — Project 1: Employee Task Manager
Review the companion · Assignment
Apply the first four lessons to a small application for one employee and their tasks. Build from requirements, using the earlier examples when you need a pattern.
1. Start here
Begin by reading the requirements and planning your model and interface. Then work through implementation, verification and reflection at your own pace. The checkpoints below help you decide what to work on next.
Environment: local. Data: webapp/model/tasks.json. Persistence: browser memory only.
Create a new working folder named employee-task-manager alongside your completed Lesson 4 project. Copy webapp, package.json, package-lock.json, ui5.yaml, .gitignore and README.md from that project into the new folder. Leave node_modules, dist and .git behind, and preserve the original project. If you need to recover the previous lesson, use the completed Lesson 4 checkpoint and trace its working operations before adapting them.
Keep the established training.fiori.day1 namespace; the outer folder name does not change the application's identity. Stop the previous server, open employee-task-manager in VS Code, run npm ci, then npm start.
Starting check: your copied Employee Directory still loads and its actions work. Use it as your own reference while adapting the Main View and Main Controller into Employee Task Manager. You will create the task data file in step A and replace the employee-specific bindings and handlers as you work through the checkpoints.
2. Understand the idea
A team manager needs to view one employee, see their tasks, add a task, switch a task between Open and Done, and delete a task.
Your app needs a single screen containing an employee summary, a labeled task-title input, an Add Task button, and a bound task list with status/update/delete controls. Use ordinary SAPUI5 controls. You do not need additional routes, dialogs, fragments, formatters, OData, BAS or Fiori elements for this project.
The local draftTask object means unfinished form input. It is unrelated to the OData draft feature introduced later in the course.
3. Build it
A. Create the task data
Create webapp/model/tasks.json with the following contents. The Employee Directory's employees.json is only a reference; the task manager will load this new file.
webapp/model/tasks.json — complete file
json
{
"employee": {
"id": 1001,
"name": "Anna Meyer",
"department": "Sales",
"status": "Active"
},
"tasks": [
{
"id": 1,
"title": "Prepare weekly report",
"status": "Open"
},
{
"id": 2,
"title": "Contact customer",
"status": "Done"
}
],
"draftTask": {
"title": ""
}
}Write down which binding should display the employee name, which binding should repeat the tasks, and which binding should connect the input to form state.
| Data | Path |
|---|---|
| Employee name | /employee/name |
| Task collection | /tasks |
| New task input | /draftTask/title |
| Title inside a task row | title, relative to that row's context |
B. Plan using patterns you already know
| Requirement | Pattern to reuse |
|---|---|
| Declare controls and handlers | Lesson 1, Build D–E; Lesson 3, Build B–C |
| Find the correct file/module | Lesson 2, Understand and Build A–B |
| Load seed JSON with loading/error handling | Lesson 4, Build C–D |
| Bind the form and collection | Lesson 4, Build B |
| Validate and add a record | Lesson 4, onAddEmployee |
| Identify/update a row | Lesson 4, onToggleEmployee and Build E |
| Delete the intended record | Lesson 4, onDeleteEmployee |
| Make a clean Git checkpoint | Lesson 2, Build D |
C. Implement in four checkpoints
Checkpoint 1 — Read: replace the Employee Directory's form and table with the employee summary and task list, and set the page title to Employee Task Manager. Adapt the Main Controller to load tasks.json into a default JSONModel. Initialize employee, tasks and draftTask before requesting data. Replace the old employee bindings and handlers with their task equivalents, keeping the View's event names and Controller methods aligned. Keep Add unavailable until the request succeeds; show a useful failure message. Verify Anna and the two seed tasks are visible.
Checkpoint 2 — Create: add a labeled input bound to /draftTask/title. Trim the title; reject empty or whitespace-only input. Create a task with an unused numeric ID and status Open. Update /tasks through setProperty and clear the form. Verify the new record appears without a page reload.
Checkpoint 3 — Update/delete: place both action buttons inside the bound row template. Obtain the row context from the event source. Toggle Open/Done on the selected record. Delete by the selected task's ID, using filter and setProperty. Verify the remaining row actions still work after a deletion.
Checkpoint 4 — Quality: check semantic IDs, labels, keyboard operation, loading failures, narrow layouts and Console errors. For bound templates, use semantic template/control IDs and templateShareable: false; let UI5 assign distinct clone IDs.
A List with CustomListItem is one possible layout. A responsive table also meets the requirement. For a CustomListItem, put a VBox inside its content and then add title, status and action controls. Look up unfamiliar controls in the API Reference rather than guessing properties.
Files to change: create webapp/model/tasks.json and adapt webapp/view/Main.view.xml and webapp/controller/Main.controller.js. Keep the seed structure shown above. Set appTitle and title in webapp/i18n/i18n.properties, and the HTML <title> in webapp/index.html, to Employee Task Manager. Keep the generated App View, Component and routing configuration. Once the task manager works, remove the unused webapp/model/employees.json from this project copy and check that no request or binding still depends on it. Localization itself is covered in Lesson 9.
4. Verify your result
Use this checklist as your definition of done. Each required behavior must work; optional decoration does not compensate for a missing operation.
| Test | Expected result |
|---|---|
Start using npm start | The app opens and shows employee data plus two seed tasks. |
Add Book a meeting room | One Open task appears and the input clears. |
| Submit empty input or spaces | No task added; the field explains what to enter. |
| Toggle the newly added task twice | Open → Done → Open; other tasks stay unchanged. |
| Delete the first task, then toggle another | The intended remaining task changes correctly. |
| Delete every task, then add a task | Empty state is understandable; creation still works. |
| Simulate a missing seed file | Error shown; Add remains disabled. Restore the file afterward. |
| Reload after changes | The original employee and two seed tasks return. |
| Use a narrow viewport and keyboard | Text/actions remain usable and fields/buttons are reachable. |
| Inspect Console and build | No application runtime errors; npm run build completes. |
| Inspect Git | At least one meaningful project commit; dependencies/build output excluded. |
Expected screen: Employee Task Manager, an employee summary, a labeled task-title input with Add Task, and a task list with status/update/delete controls.
Your layout can differ from the reference implementation. Completed Lesson 5 reference is available for comparison after attempting the project. If you use it to recover, identify and explain each relevant handler rather than copying it without tracing the data flow.
5. Troubleshoot
Use the first relevant clue: read Console, inspect a failed Network request, check binding paths/model names, check handler names/imports, and inspect model data. Change one cause at a time and re-run the failing action.
Hint 1 — the task list is empty
Check that the JSON request succeeds and that the model is attached to the same View. The collection is /tasks; title and status are relative bindings inside each row. The input uses /draftTask/title.
Hint 2 — creation does not appear
Validate the draft title, build a new object, then call setProperty("/tasks", aTasks.concat(oTask)). Do not only mutate the JavaScript array or add a control manually.
Hint 3 — the wrong task changes or disappears
Start with the row button's event source. Retrieve its binding context at the time of the action. For update, use the context path; for deletion, retrieve the task ID and filter the collection by that ID. Do not hard-code /tasks/0.
Hint 4 — row buttons have no context
They need to be children of the bound row. A toolbar button outside the list does not inherit a particular task's context. Keep the default model consistent across list binding and getBindingContext().
6. Check your understanding
- Which values come from the seed JSON, and which are created at runtime?
- What connects a row's button with a particular task?
- Why does deletion still work after row positions change?
- Why do your changes disappear after reload?
- What would need to change to make tasks permanent?
Suggested answers
- The employee and two starting tasks come from JSON. Added tasks and changed statuses exist in the running model.
- The button inherits the row's binding context; its event handler can read that context.
- The handler retrieves the selected record's ID rather than relying on a screen position.
- A fresh app run reloads the original seed file; JSONModel does not automatically write to it.
- The application would need explicit persistence, such as an OData-backed service. Replacing the model also changes loading, mutation and error-handling APIs; it is not just changing a URL.
7. Continue to Lesson 6
Commit your result and keep both Lesson 4 and Project 1. You can now build a single-screen SAPUI5 application with local CRUD behavior. Lesson 6 deepens binding contexts and list/detail patterns; Lessons 7–9 add dialogs, navigation, formatting, i18n and tests.
8. Official references
Use the SAPUI5 version selector to read the API for 1.148.12, the version used by these checkpoints. Documentation checked on 15 November 2026.