Skip to content

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.

DataPath
Employee name/employee/name
Task collection/tasks
New task input/draftTask/title
Title inside a task rowtitle, relative to that row's context

B. Plan using patterns you already know ​

RequirementPattern to reuse
Declare controls and handlersLesson 1, Build D–E; Lesson 3, Build B–C
Find the correct file/moduleLesson 2, Understand and Build A–B
Load seed JSON with loading/error handlingLesson 4, Build C–D
Bind the form and collectionLesson 4, Build B
Validate and add a recordLesson 4, onAddEmployee
Identify/update a rowLesson 4, onToggleEmployee and Build E
Delete the intended recordLesson 4, onDeleteEmployee
Make a clean Git checkpointLesson 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.

TestExpected result
Start using npm startThe app opens and shows employee data plus two seed tasks.
Add Book a meeting roomOne Open task appears and the input clears.
Submit empty input or spacesNo task added; the field explains what to enter.
Toggle the newly added task twiceOpen → Done → Open; other tasks stay unchanged.
Delete the first task, then toggle anotherThe intended remaining task changes correctly.
Delete every task, then add a taskEmpty state is understandable; creation still works.
Simulate a missing seed fileError shown; Add remains disabled. Restore the file afterward.
Reload after changesThe original employee and two seed tasks return.
Use a narrow viewport and keyboardText/actions remain usable and fields/buttons are reachable.
Inspect Console and buildNo application runtime errors; npm run build completes.
Inspect GitAt 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 ​

  1. Which values come from the seed JSON, and which are created at runtime?
  2. What connects a row's button with a particular task?
  3. Why does deletion still work after row positions change?
  4. Why do your changes disappear after reload?
  5. What would need to change to make tasks permanent?
Suggested answers
  1. The employee and two starting tasks come from JSON. Added tasks and changed statuses exist in the running model.
  2. The button inherits the row's binding context; its event handler can read that context.
  3. The handler retrieves the selected record's ID rather than relying on a screen position.
  4. A fresh app run reloads the original seed file; JSONModel does not automatically write to it.
  5. 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.

Independent learning materials for SAP frontend development.