---
title: "Angular Timeline Role-Based Access Example | Mobiscroll"
component: "Timeline"
framework: "Angular"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/angular/timeline/role-based-views-with-different-permission"
---

# Role-Based Access - Angular Timeline demo

Implement role-based access in a Angular Timeline: managers edit all tasks, employees edit their own, and clients have read-only access.

- [Live demo](https://demo.mobiscroll.com/angular/timeline/role-based-views-with-different-permission)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-angular/tree/main/src/demos/eventcalendar/timeline/role-based-views-with-different-permission)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/timeline/role-based-views-with-different-permission.md), [jQuery](https://demo.mobiscroll.com/jquery/timeline/role-based-views-with-different-permission.md), [React](https://demo.mobiscroll.com/react/timeline/role-based-views-with-different-permission.md), [Vue](https://demo.mobiscroll.com/vue/timeline/role-based-views-with-different-permission.md)

## Description

The following example demonstrates how to implement role-based permissions in a calendar by simulating a logged in user. The selected user determines which role and permissions are applied:

- **Project manager (Full access)** - can manage all tasks
- **Employees (Limited access)** - can only edit their own tasks
- **Clients (Read-only)** - can view the schedule without making changes

The demo uses an outside control to simulate logging in as a specific user. Based on the chosen role, the calendar applies the corresponding permissions conditionally.

This approach shows how you could pass the logged in user's role from your authentication system and dynamically configure what actions are allowed in the timeline.

## What this demo shows

- A desktop weekly timeline for role-based access control, with days arranged horizontally and resources listed as rows on the left.
- **Header navigation** The month and year label opens date navigation, while the previous and next arrows move between weeks and the Today button returns to the current date.
- **Week view** The strip below the header shows the selected week from Sunday to Saturday, with the current date highlighted.
- **Role selection** The demo simulates different logged-in users to show how permissions change by role.
- **Full access role** The Project manager can create, edit, drag, resize, and delete tasks across all resources.
- **Limited access role** Employees can view the full schedule but can only modify tasks assigned to themselves.
- **Employee preview** Selecting different employees shows the editing permissions for each employee.
- **Read-only role** Clients can browse the full schedule but cannot create, edit, move, resize, or delete tasks.
- **Permission handling** Editing capabilities are enabled or disabled automatically according to the active user role.
- **Shared timeline data** The same timeline data is shown with different interaction levels without changing the underlying schedule.
- **Time grid** The timeline displays hourly columns from 8 AM to 8 PM.
- **Resources** Multiple resources are shown as separate timeline rows.
- **Current time** A vertical blue line with a time label marks the current time.
- **Hover behavior** Hovering over the time grid shows a time indicator that follows the cursor in 15-minute increments.
- **Event cards** Events are shown as colored cards with a left color stripe, a bold title, a description, and a bold time range.
- **Date positioning** Events are positioned by their assigned resource and exact date and time range.
- **Event interaction** Editable events highlight on hover and show drag and resize handles for repositioning or changing duration.
- **Event selection** Clicking an event selects and highlights it.
- **Event creation** New events can be created by double-clicking the timeline or by clicking and dragging across a time range when the active role allows it.
- **Scrolling** The timeline supports horizontal and vertical scrolling for navigating through time and resources.

## Best for

- **Frontend permission handling** Demonstrating how to apply role-based editing rules while keeping a shared timeline interface visible to every user.
- **Project management tools** Showing different task management permissions for managers, team members, and external clients.
- **Workforce scheduling** Letting employees view the full team timeline while limiting edits to their own assigned work.
- **Team collaboration apps** Supporting shared planning views where each role has a different level of control over the same timeline.
- **Client-facing timeline** Providing read-only access to project timelines without exposing editing actions.
- **Permission testing** Previewing how the same timeline behaves for full access, limited access, and read-only users.
- **Resource-based timelines** Managing tasks across multiple people or resources in a weekly business-hours timeline.

## Tutorial

### Simulate logged in user

- ( ) Full access - Project manager
- (x) Limited access `Willis Cane`- Employee
- ( ) Read-only access - Client

```html
<mbsc-eventcalendar
  [data]="myEvents"
  [resources]="myResources"
  [view]="myView"
  [clickToCreate]="editEvents"
  [dragToCreate]="editEvents"
  [dragToMove]="editEvents"
  [dragToResize]="editEvents"
  [eventDelete]="editEvents"
  [extendDefaultEvent]="myDefaultEvent">
</mbsc-eventcalendar>
```

```ts
// Simulated logged in user
user = {
  id: 2,
  name: 'Willis Cane',
  role: 'limited'
};

editEvents = false;
myDefaultEvent(): MbscCalendarEvent {
  return {};
}

myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    startTime: '08:00',
    endTime: '20:00',
  },
};

myEvents: MbscCalendarEvent[] = [{
  start: '2026-10-24T11:00',
  end: '2026-10-24T15:00',
  title: 'Task 1',
  resource: 1
}, {
  start: '2026-10-24T14:00',
  end: '2026-10-24T17:00',
  title: 'Task 2',
  resource: 3
}, {
  start: '2026-10-24T12:00',
  end: '2026-10-24T14:00',
  title: 'Task 3',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T15:00',
  title: 'Task 4',
  resource: 1
}, {
  start: '2026-10-25T11:00',
  end: '2026-10-25T13:00',
  title: 'Task 5',
  resource: 2
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T17:00',
  title: 'Task 6',
  resource: 2
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T15:00',
  title: 'Task 7',
  resource: 3
}, {
  start: '2026-10-25T17:00',
  end: '2026-10-25T20:00',
  title: 'Task 8',
  resource: 3
}, {
  start: '2026-10-25T08:00',
  end: '2026-10-25T11:30',
  title: 'Task 9',
  resource: 4
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T14:00',
  title: 'Task 10',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T13:00',
  title: 'Task 11',
  resource: 5
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T16:00',
  title: 'Task 12',
  resource: 5
}, {      
  start: '2026-10-25T16:30',
  end: '2026-10-25T19:00',
  title: 'Task 13',
  resource: 5
}, {
  start: '2026-10-26T11:00',
  end: '2026-10-26T14:00',
  title: 'Task 14',
  resource: 2
}, {
  start: '2026-10-26T16:00',
  end: '2026-10-26T20:00',
  title: 'Task 15',
  resource: 5
}]

myResources: MbscResource[] = [{
  id: 1,
  name: 'Jude Chester',
  color: '#af2ec3'
}, {
  id: 2,
  name: 'Willis Cane',
  color: '#cccc39'
}, {
  id: 3,
  name: 'Derek Austyn',
  color: '#56ca2c'
}, {
  id: 4,
  name: 'Merv Kenny',
  color: '#af2424'
}, {
  id: 5,
  name: 'Fred Waldez',
  color: '#256ebc'
}]

// Simulate login
login(): void {
  const newTasks = [...this.myEvents];
  const newResources = [...this.myResources];
  let defaultColor = '';

  if (this.user.role === 'readonly') {
    for (const task of newTasks) {
      // Disable editing for all events
      task.editable = false;
      // Make event colors uniform
      task.color = '#af2ec3';
    }
  } else if (this.user.role === 'limited') {
    defaultColor = '#af2424';
    for (const task of newTasks) {
      if (task.resource !== user.id) {
        // Disable editing events of other users
        task.editable = false
        // Set disabled event colors to gray
        task.color = '#6a6a6a'
      } else {
        // Make event colors uniform
        task.color = '#af2424'
      }
    }

    for (const res of newResources) {
      if (res.id !== this.user.id) {
        // Disable event creation for other users
        res.eventCreation = false;
      }
    }
  }

  // Update events, resources and d&d options
  this.myEvents = newTasks;
  this.myResources = newResources;
  this.editEvents = this.user.role != 'readonly';
  this.myDefaultEvent = function (): MbscCalendarEvent {
    return {
      color: defaultColor
    };
  }
}

ngOnInit(): void {
  this.login();
}
```

With "Full access - Project manager":

```ts
// Simulated logged in user
user = {
  id: 'client'
  name: 'Project manager',
  role: 'full'
};

editEvents = false;
myDefaultEvent(): MbscCalendarEvent {
  return {};
}

myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    startTime: '08:00',
    endTime: '20:00',
  },
};

myEvents: MbscCalendarEvent[] = [{
  start: '2026-10-24T11:00',
  end: '2026-10-24T15:00',
  title: 'Task 1',
  resource: 1
}, {
  start: '2026-10-24T14:00',
  end: '2026-10-24T17:00',
  title: 'Task 2',
  resource: 3
}, {
  start: '2026-10-24T12:00',
  end: '2026-10-24T14:00',
  title: 'Task 3',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T15:00',
  title: 'Task 4',
  resource: 1
}, {
  start: '2026-10-25T11:00',
  end: '2026-10-25T13:00',
  title: 'Task 5',
  resource: 2
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T17:00',
  title: 'Task 6',
  resource: 2
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T15:00',
  title: 'Task 7',
  resource: 3
}, {
  start: '2026-10-25T17:00',
  end: '2026-10-25T20:00',
  title: 'Task 8',
  resource: 3
}, {
  start: '2026-10-25T08:00',
  end: '2026-10-25T11:30',
  title: 'Task 9',
  resource: 4
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T14:00',
  title: 'Task 10',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T13:00',
  title: 'Task 11',
  resource: 5
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T16:00',
  title: 'Task 12',
  resource: 5
}, {      
  start: '2026-10-25T16:30',
  end: '2026-10-25T19:00',
  title: 'Task 13',
  resource: 5
}, {
  start: '2026-10-26T11:00',
  end: '2026-10-26T14:00',
  title: 'Task 14',
  resource: 2
}, {
  start: '2026-10-26T16:00',
  end: '2026-10-26T20:00',
  title: 'Task 15',
  resource: 5
}]

myResources: MbscResource[] = [{
  id: 1,
  name: 'Jude Chester',
  color: '#af2ec3'
}, {
  id: 2,
  name: 'Willis Cane',
  color: '#cccc39'
}, {
  id: 3,
  name: 'Derek Austyn',
  color: '#56ca2c'
}, {
  id: 4,
  name: 'Merv Kenny',
  color: '#af2424'
}, {
  id: 5,
  name: 'Fred Waldez',
  color: '#256ebc'
}]

// Simulate login
login(): void {
  const newTasks = [...this.myEvents];
  const newResources = [...this.myResources];
  let defaultColor = '';

  if (this.user.role === 'readonly') {
    for (const task of newTasks) {
      // Disable editing for all events
      task.editable = false;
      // Make event colors uniform
      task.color = '#af2ec3';
    }
  } else if (this.user.role === 'limited') {
    defaultColor = '#af2424';
    for (const task of newTasks) {
      if (task.resource !== user.id) {
        // Disable editing events of other users
        task.editable = false
        // Set disabled event colors to gray
        task.color = '#6a6a6a'
      } else {
        // Make event colors uniform
        task.color = '#af2424'
      }
    }

    for (const res of newResources) {
      if (res.id !== this.user.id) {
        // Disable event creation for other users
        res.eventCreation = false;
      }
    }
  }

  // Update events, resources and d&d options
  this.myEvents = newTasks;
  this.myResources = newResources;
  this.editEvents = this.user.role != 'readonly';
  this.myDefaultEvent = function (): MbscCalendarEvent {
    return {
      color: defaultColor
    };
  }
}

ngOnInit(): void {
  this.login();
}
```

With "Read-only access - Client":

```ts
// Simulated logged in user
user = {
  id: 'client'
  name: 'Client',
  role: 'readonly'
};

editEvents = false;
myDefaultEvent(): MbscCalendarEvent {
  return {};
}

myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    startTime: '08:00',
    endTime: '20:00',
  },
};

myEvents: MbscCalendarEvent[] = [{
  start: '2026-10-24T11:00',
  end: '2026-10-24T15:00',
  title: 'Task 1',
  resource: 1
}, {
  start: '2026-10-24T14:00',
  end: '2026-10-24T17:00',
  title: 'Task 2',
  resource: 3
}, {
  start: '2026-10-24T12:00',
  end: '2026-10-24T14:00',
  title: 'Task 3',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T15:00',
  title: 'Task 4',
  resource: 1
}, {
  start: '2026-10-25T11:00',
  end: '2026-10-25T13:00',
  title: 'Task 5',
  resource: 2
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T17:00',
  title: 'Task 6',
  resource: 2
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T15:00',
  title: 'Task 7',
  resource: 3
}, {
  start: '2026-10-25T17:00',
  end: '2026-10-25T20:00',
  title: 'Task 8',
  resource: 3
}, {
  start: '2026-10-25T08:00',
  end: '2026-10-25T11:30',
  title: 'Task 9',
  resource: 4
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T14:00',
  title: 'Task 10',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T13:00',
  title: 'Task 11',
  resource: 5
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T16:00',
  title: 'Task 12',
  resource: 5
}, {      
  start: '2026-10-25T16:30',
  end: '2026-10-25T19:00',
  title: 'Task 13',
  resource: 5
}, {
  start: '2026-10-26T11:00',
  end: '2026-10-26T14:00',
  title: 'Task 14',
  resource: 2
}, {
  start: '2026-10-26T16:00',
  end: '2026-10-26T20:00',
  title: 'Task 15',
  resource: 5
}]

myResources: MbscResource[] = [{
  id: 1,
  name: 'Jude Chester',
  color: '#af2ec3'
}, {
  id: 2,
  name: 'Willis Cane',
  color: '#cccc39'
}, {
  id: 3,
  name: 'Derek Austyn',
  color: '#56ca2c'
}, {
  id: 4,
  name: 'Merv Kenny',
  color: '#af2424'
}, {
  id: 5,
  name: 'Fred Waldez',
  color: '#256ebc'
}]

// Simulate login
login(): void {
  const newTasks = [...this.myEvents];
  const newResources = [...this.myResources];
  let defaultColor = '';

  if (this.user.role === 'readonly') {
    for (const task of newTasks) {
      // Disable editing for all events
      task.editable = false;
      // Make event colors uniform
      task.color = '#af2ec3';
    }
  } else if (this.user.role === 'limited') {
    defaultColor = '#af2424';
    for (const task of newTasks) {
      if (task.resource !== user.id) {
        // Disable editing events of other users
        task.editable = false
        // Set disabled event colors to gray
        task.color = '#6a6a6a'
      } else {
        // Make event colors uniform
        task.color = '#af2424'
      }
    }

    for (const res of newResources) {
      if (res.id !== this.user.id) {
        // Disable event creation for other users
        res.eventCreation = false;
      }
    }
  }

  // Update events, resources and d&d options
  this.myEvents = newTasks;
  this.myResources = newResources;
  this.editEvents = this.user.role != 'readonly';
  this.myDefaultEvent = function (): MbscCalendarEvent {
    return {
      color: defaultColor
    };
  }
}

ngOnInit(): void {
  this.login();
}
```

With "Jude Chester":

```ts
// Simulated logged in user
user = {
  id: 1,
  name: 'Jude Chester',
  role: 'limited'
};

editEvents = false;
myDefaultEvent(): MbscCalendarEvent {
  return {};
}

myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    startTime: '08:00',
    endTime: '20:00',
  },
};

myEvents: MbscCalendarEvent[] = [{
  start: '2026-10-24T11:00',
  end: '2026-10-24T15:00',
  title: 'Task 1',
  resource: 1
}, {
  start: '2026-10-24T14:00',
  end: '2026-10-24T17:00',
  title: 'Task 2',
  resource: 3
}, {
  start: '2026-10-24T12:00',
  end: '2026-10-24T14:00',
  title: 'Task 3',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T15:00',
  title: 'Task 4',
  resource: 1
}, {
  start: '2026-10-25T11:00',
  end: '2026-10-25T13:00',
  title: 'Task 5',
  resource: 2
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T17:00',
  title: 'Task 6',
  resource: 2
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T15:00',
  title: 'Task 7',
  resource: 3
}, {
  start: '2026-10-25T17:00',
  end: '2026-10-25T20:00',
  title: 'Task 8',
  resource: 3
}, {
  start: '2026-10-25T08:00',
  end: '2026-10-25T11:30',
  title: 'Task 9',
  resource: 4
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T14:00',
  title: 'Task 10',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T13:00',
  title: 'Task 11',
  resource: 5
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T16:00',
  title: 'Task 12',
  resource: 5
}, {      
  start: '2026-10-25T16:30',
  end: '2026-10-25T19:00',
  title: 'Task 13',
  resource: 5
}, {
  start: '2026-10-26T11:00',
  end: '2026-10-26T14:00',
  title: 'Task 14',
  resource: 2
}, {
  start: '2026-10-26T16:00',
  end: '2026-10-26T20:00',
  title: 'Task 15',
  resource: 5
}]

myResources: MbscResource[] = [{
  id: 1,
  name: 'Jude Chester',
  color: '#af2ec3'
}, {
  id: 2,
  name: 'Willis Cane',
  color: '#cccc39'
}, {
  id: 3,
  name: 'Derek Austyn',
  color: '#56ca2c'
}, {
  id: 4,
  name: 'Merv Kenny',
  color: '#af2424'
}, {
  id: 5,
  name: 'Fred Waldez',
  color: '#256ebc'
}]

// Simulate login
login(): void {
  const newTasks = [...this.myEvents];
  const newResources = [...this.myResources];
  let defaultColor = '';

  if (this.user.role === 'readonly') {
    for (const task of newTasks) {
      // Disable editing for all events
      task.editable = false;
      // Make event colors uniform
      task.color = '#af2ec3';
    }
  } else if (this.user.role === 'limited') {
    defaultColor = '#af2424';
    for (const task of newTasks) {
      if (task.resource !== user.id) {
        // Disable editing events of other users
        task.editable = false
        // Set disabled event colors to gray
        task.color = '#6a6a6a'
      } else {
        // Make event colors uniform
        task.color = '#af2424'
      }
    }

    for (const res of newResources) {
      if (res.id !== this.user.id) {
        // Disable event creation for other users
        res.eventCreation = false;
      }
    }
  }

  // Update events, resources and d&d options
  this.myEvents = newTasks;
  this.myResources = newResources;
  this.editEvents = this.user.role != 'readonly';
  this.myDefaultEvent = function (): MbscCalendarEvent {
    return {
      color: defaultColor
    };
  }
}

ngOnInit(): void {
  this.login();
}
```

With "Derek Austyn":

```ts
// Simulated logged in user
user = {
  id: 3,
  name: 'Derek Austyn',
  role: 'limited'
};

editEvents = false;
myDefaultEvent(): MbscCalendarEvent {
  return {};
}

myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    startTime: '08:00',
    endTime: '20:00',
  },
};

myEvents: MbscCalendarEvent[] = [{
  start: '2026-10-24T11:00',
  end: '2026-10-24T15:00',
  title: 'Task 1',
  resource: 1
}, {
  start: '2026-10-24T14:00',
  end: '2026-10-24T17:00',
  title: 'Task 2',
  resource: 3
}, {
  start: '2026-10-24T12:00',
  end: '2026-10-24T14:00',
  title: 'Task 3',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T15:00',
  title: 'Task 4',
  resource: 1
}, {
  start: '2026-10-25T11:00',
  end: '2026-10-25T13:00',
  title: 'Task 5',
  resource: 2
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T17:00',
  title: 'Task 6',
  resource: 2
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T15:00',
  title: 'Task 7',
  resource: 3
}, {
  start: '2026-10-25T17:00',
  end: '2026-10-25T20:00',
  title: 'Task 8',
  resource: 3
}, {
  start: '2026-10-25T08:00',
  end: '2026-10-25T11:30',
  title: 'Task 9',
  resource: 4
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T14:00',
  title: 'Task 10',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T13:00',
  title: 'Task 11',
  resource: 5
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T16:00',
  title: 'Task 12',
  resource: 5
}, {      
  start: '2026-10-25T16:30',
  end: '2026-10-25T19:00',
  title: 'Task 13',
  resource: 5
}, {
  start: '2026-10-26T11:00',
  end: '2026-10-26T14:00',
  title: 'Task 14',
  resource: 2
}, {
  start: '2026-10-26T16:00',
  end: '2026-10-26T20:00',
  title: 'Task 15',
  resource: 5
}]

myResources: MbscResource[] = [{
  id: 1,
  name: 'Jude Chester',
  color: '#af2ec3'
}, {
  id: 2,
  name: 'Willis Cane',
  color: '#cccc39'
}, {
  id: 3,
  name: 'Derek Austyn',
  color: '#56ca2c'
}, {
  id: 4,
  name: 'Merv Kenny',
  color: '#af2424'
}, {
  id: 5,
  name: 'Fred Waldez',
  color: '#256ebc'
}]

// Simulate login
login(): void {
  const newTasks = [...this.myEvents];
  const newResources = [...this.myResources];
  let defaultColor = '';

  if (this.user.role === 'readonly') {
    for (const task of newTasks) {
      // Disable editing for all events
      task.editable = false;
      // Make event colors uniform
      task.color = '#af2ec3';
    }
  } else if (this.user.role === 'limited') {
    defaultColor = '#af2424';
    for (const task of newTasks) {
      if (task.resource !== user.id) {
        // Disable editing events of other users
        task.editable = false
        // Set disabled event colors to gray
        task.color = '#6a6a6a'
      } else {
        // Make event colors uniform
        task.color = '#af2424'
      }
    }

    for (const res of newResources) {
      if (res.id !== this.user.id) {
        // Disable event creation for other users
        res.eventCreation = false;
      }
    }
  }

  // Update events, resources and d&d options
  this.myEvents = newTasks;
  this.myResources = newResources;
  this.editEvents = this.user.role != 'readonly';
  this.myDefaultEvent = function (): MbscCalendarEvent {
    return {
      color: defaultColor
    };
  }
}

ngOnInit(): void {
  this.login();
}
```

With "Merv Kenny":

```ts
// Simulated logged in user
user = {
  id: 4,
  name: 'Merv Kenny',
  role: 'limited'
};

editEvents = false;
myDefaultEvent(): MbscCalendarEvent {
  return {};
}

myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    startTime: '08:00',
    endTime: '20:00',
  },
};

myEvents: MbscCalendarEvent[] = [{
  start: '2026-10-24T11:00',
  end: '2026-10-24T15:00',
  title: 'Task 1',
  resource: 1
}, {
  start: '2026-10-24T14:00',
  end: '2026-10-24T17:00',
  title: 'Task 2',
  resource: 3
}, {
  start: '2026-10-24T12:00',
  end: '2026-10-24T14:00',
  title: 'Task 3',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T15:00',
  title: 'Task 4',
  resource: 1
}, {
  start: '2026-10-25T11:00',
  end: '2026-10-25T13:00',
  title: 'Task 5',
  resource: 2
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T17:00',
  title: 'Task 6',
  resource: 2
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T15:00',
  title: 'Task 7',
  resource: 3
}, {
  start: '2026-10-25T17:00',
  end: '2026-10-25T20:00',
  title: 'Task 8',
  resource: 3
}, {
  start: '2026-10-25T08:00',
  end: '2026-10-25T11:30',
  title: 'Task 9',
  resource: 4
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T14:00',
  title: 'Task 10',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T13:00',
  title: 'Task 11',
  resource: 5
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T16:00',
  title: 'Task 12',
  resource: 5
}, {      
  start: '2026-10-25T16:30',
  end: '2026-10-25T19:00',
  title: 'Task 13',
  resource: 5
}, {
  start: '2026-10-26T11:00',
  end: '2026-10-26T14:00',
  title: 'Task 14',
  resource: 2
}, {
  start: '2026-10-26T16:00',
  end: '2026-10-26T20:00',
  title: 'Task 15',
  resource: 5
}]

myResources: MbscResource[] = [{
  id: 1,
  name: 'Jude Chester',
  color: '#af2ec3'
}, {
  id: 2,
  name: 'Willis Cane',
  color: '#cccc39'
}, {
  id: 3,
  name: 'Derek Austyn',
  color: '#56ca2c'
}, {
  id: 4,
  name: 'Merv Kenny',
  color: '#af2424'
}, {
  id: 5,
  name: 'Fred Waldez',
  color: '#256ebc'
}]

// Simulate login
login(): void {
  const newTasks = [...this.myEvents];
  const newResources = [...this.myResources];
  let defaultColor = '';

  if (this.user.role === 'readonly') {
    for (const task of newTasks) {
      // Disable editing for all events
      task.editable = false;
      // Make event colors uniform
      task.color = '#af2ec3';
    }
  } else if (this.user.role === 'limited') {
    defaultColor = '#af2424';
    for (const task of newTasks) {
      if (task.resource !== user.id) {
        // Disable editing events of other users
        task.editable = false
        // Set disabled event colors to gray
        task.color = '#6a6a6a'
      } else {
        // Make event colors uniform
        task.color = '#af2424'
      }
    }

    for (const res of newResources) {
      if (res.id !== this.user.id) {
        // Disable event creation for other users
        res.eventCreation = false;
      }
    }
  }

  // Update events, resources and d&d options
  this.myEvents = newTasks;
  this.myResources = newResources;
  this.editEvents = this.user.role != 'readonly';
  this.myDefaultEvent = function (): MbscCalendarEvent {
    return {
      color: defaultColor
    };
  }
}

ngOnInit(): void {
  this.login();
}
```

With "Fred Waldez":

```ts
// Simulated logged in user
user = {
  id: 5,
  name: 'Fred Waldez',
  role: 'limited'
};

editEvents = false;
myDefaultEvent(): MbscCalendarEvent {
  return {};
}

myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    startTime: '08:00',
    endTime: '20:00',
  },
};

myEvents: MbscCalendarEvent[] = [{
  start: '2026-10-24T11:00',
  end: '2026-10-24T15:00',
  title: 'Task 1',
  resource: 1
}, {
  start: '2026-10-24T14:00',
  end: '2026-10-24T17:00',
  title: 'Task 2',
  resource: 3
}, {
  start: '2026-10-24T12:00',
  end: '2026-10-24T14:00',
  title: 'Task 3',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T15:00',
  title: 'Task 4',
  resource: 1
}, {
  start: '2026-10-25T11:00',
  end: '2026-10-25T13:00',
  title: 'Task 5',
  resource: 2
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T17:00',
  title: 'Task 6',
  resource: 2
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T15:00',
  title: 'Task 7',
  resource: 3
}, {
  start: '2026-10-25T17:00',
  end: '2026-10-25T20:00',
  title: 'Task 8',
  resource: 3
}, {
  start: '2026-10-25T08:00',
  end: '2026-10-25T11:30',
  title: 'Task 9',
  resource: 4
}, {
  start: '2026-10-25T12:00',
  end: '2026-10-25T14:00',
  title: 'Task 10',
  resource: 4
}, {
  start: '2026-10-25T10:00',
  end: '2026-10-25T13:00',
  title: 'Task 11',
  resource: 5
}, {
  start: '2026-10-25T14:00',
  end: '2026-10-25T16:00',
  title: 'Task 12',
  resource: 5
}, {      
  start: '2026-10-25T16:30',
  end: '2026-10-25T19:00',
  title: 'Task 13',
  resource: 5
}, {
  start: '2026-10-26T11:00',
  end: '2026-10-26T14:00',
  title: 'Task 14',
  resource: 2
}, {
  start: '2026-10-26T16:00',
  end: '2026-10-26T20:00',
  title: 'Task 15',
  resource: 5
}]

myResources: MbscResource[] = [{
  id: 1,
  name: 'Jude Chester',
  color: '#af2ec3'
}, {
  id: 2,
  name: 'Willis Cane',
  color: '#cccc39'
}, {
  id: 3,
  name: 'Derek Austyn',
  color: '#56ca2c'
}, {
  id: 4,
  name: 'Merv Kenny',
  color: '#af2424'
}, {
  id: 5,
  name: 'Fred Waldez',
  color: '#256ebc'
}]

// Simulate login
login(): void {
  const newTasks = [...this.myEvents];
  const newResources = [...this.myResources];
  let defaultColor = '';

  if (this.user.role === 'readonly') {
    for (const task of newTasks) {
      // Disable editing for all events
      task.editable = false;
      // Make event colors uniform
      task.color = '#af2ec3';
    }
  } else if (this.user.role === 'limited') {
    defaultColor = '#af2424';
    for (const task of newTasks) {
      if (task.resource !== user.id) {
        // Disable editing events of other users
        task.editable = false
        // Set disabled event colors to gray
        task.color = '#6a6a6a'
      } else {
        // Make event colors uniform
        task.color = '#af2424'
      }
    }

    for (const res of newResources) {
      if (res.id !== this.user.id) {
        // Disable event creation for other users
        res.eventCreation = false;
      }
    }
  }

  // Update events, resources and d&d options
  this.myEvents = newTasks;
  this.myResources = newResources;
  this.editEvents = this.user.role != 'readonly';
  this.myDefaultEvent = function (): MbscCalendarEvent {
    return {
      color: defaultColor
    };
  }
}

ngOnInit(): void {
  this.login();
}
```

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-themeVariant) - option
- [`data`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-data) - option
- [`resources`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-resources) - option
- [`view`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-view) - option
- [`clickToCreate`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-clickToCreate) - option
- [`dragToCreate`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-dragToCreate) - option
- [`dragToMove`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-dragToMove) - option
- [`dragToResize`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-dragToResize) - option
- [`eventDelete`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-eventDelete) - option
- [`extendDefaultEvent`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-extendDefaultEvent) - option

## Code

### Component

```ts
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import {
  MbscCalendarEvent,
  MbscEventcalendarView,
  MbscModule,
  MbscResource,
  Notifications,
  setOptions,
} from '@mobiscroll/angular';

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

@Component({
  selector: 'app-root', 
  templateUrl: './app.component.html',
  standalone: true,
  imports: [CommonModule, MbscModule],
})
export class AppComponent implements OnInit {
  constructor(private notify: Notifications) {}

  user = { id: 2, name: 'Willis Cane', role: 'limited' };

  /* Other user examples
  user = { id: 'client', name: 'Client', role: 'readonly' };
  user = { id: 'manager', name: 'Project Manager', role: 'full' }; */

  editEvents = false;
  defaultColor = '';

  myView: MbscEventcalendarView = {
    timeline: {
      type: 'week',
      startTime: '08:00',
      endTime: '20:00',
    },
  };

  myEvents: MbscCalendarEvent[] = [
    {
      start: '2026-10-24T11:00',
      end: '2026-10-24T15:00',
      title: 'Task 1',
      resource: 1,
    },
    {
      start: '2026-10-24T14:00',
      end: '2026-10-24T17:00',
      title: 'Task 2',
      resource: 3,
    },
    {
      start: '2026-10-24T12:00',
      end: '2026-10-24T14:00',
      title: 'Task 3',
      resource: 4,
    },
    {
      start: '2026-10-25T10:00',
      end: '2026-10-25T15:00',
      title: 'Task 4',
      resource: 1,
    },
    {
      start: '2026-10-25T11:00',
      end: '2026-10-25T13:00',
      title: 'Task 5',
      resource: 2,
    },
    {
      start: '2026-10-25T14:00',
      end: '2026-10-25T17:00',
      title: 'Task 6',
      resource: 2,
    },
    {
      start: '2026-10-25T12:00',
      end: '2026-10-25T15:00',
      title: 'Task 7',
      resource: 3,
    },
    {
      start: '2026-10-25T17:00',
      end: '2026-10-25T20:00',
      title: 'Task 8',
      resource: 3,
    },
    {
      start: '2026-10-25T08:00',
      end: '2026-10-25T11:30',
      title: 'Task 9',
      resource: 4,
    },
    {
      start: '2026-10-25T12:00',
      end: '2026-10-25T14:00',
      title: 'Task 10',
      resource: 4,
    },
    {
      start: '2026-10-25T10:00',
      end: '2026-10-25T13:00',
      title: 'Task 11',
      resource: 5,
    },
    {
      start: '2026-10-25T14:00',
      end: '2026-10-25T16:00',
      title: 'Task 12',
      resource: 5,
    },
    {
      start: '2026-10-25T16:30',
      end: '2026-10-25T19:00',
      title: 'Task 13',
      resource: 5,
    },
    {
      start: '2026-10-26T11:00',
      end: '2026-10-26T14:00',
      title: 'Task 14',
      resource: 2,
    },
    {
      start: '2026-10-26T16:00',
      end: '2026-10-26T20:00',
      title: 'Task 15',
      resource: 5,
    },
  ];

  myResources: MbscResource[] = [
    { id: 1, name: 'Jude Chester', color: '#af2ec3' },
    { id: 2, name: 'Willis Cane', color: '#cccc39' },
    { id: 3, name: 'Derek Austyn', color: '#56ca2c' },
    { id: 4, name: 'Merv Kenny', color: '#af2424' },
    { id: 5, name: 'Fred Waldez', color: '#256ebc' },
  ];

  myDefaultEvent = (): MbscCalendarEvent => ({
    color: this.defaultColor,
  });

  // Simulate login
  login(): void {
    const newTasks = [...this.myEvents];
    const newResources = [...this.myResources];

    if (this.user.role === 'readonly') {
      this.defaultColor = '';
      for (const task of newTasks) {
        task.editable = false;
        task.color = '#af2ec3';
      }

      this.notify.toast({
        message: 'Client with read-only access logged in',
      });
    } else if (this.user.role === 'limited') {
      this.defaultColor = '#af2424';
      for (const task of newTasks) {
        if (task.resource !== this.user.id) {
          task.editable = false;
          task.color = '#6a6a6a';
        } else {
          task.color = '#af2424';
        }
      }

      for (const res of newResources) {
        if (res.id !== this.user.id) {
          res.eventCreation = false;
        }
      }

      this.notify.toast({
        message: 'User ' + this.user.name + ' with limited access logged in',
      });
    } else {
      this.defaultColor = '';
      this.notify.toast({
        message: 'User with full access logged in',
      });
    }

    this.myEvents = newTasks;
    this.myResources = newResources;
    this.editEvents = this.user.role != 'readonly';
  }

  ngOnInit(): void {
    this.login();
  }
}
```

### Template

```html
<mbsc-eventcalendar
  class="mds-role-based-timeline"
  [data]="myEvents"
  [resources]="myResources"
  [view]="myView"
  [clickToCreate]="editEvents"
  [dragToCreate]="editEvents"
  [dragToMove]="editEvents"
  [dragToResize]="editEvents"
  [eventDelete]="editEvents"
  [extendDefaultEvent]="myDefaultEvent"
/>
```

### CSS

```css
.mds-role-based-timeline .mbsc-schedule-event:not(.mbsc-readonly-event) .mbsc-schedule-event-background {
  border: 2px solid currentColor;
}

.mds-role-based-timeline .mbsc-schedule-event .mbsc-schedule-event-background::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.6);
}
```

## Implementation notes

- Use `timeline: { type: 'week', startTime: '08:00', endTime: '20:00' }` to show a week view restricted to business hours.
- Define 5 named employee resources (Jude Chester, Willis Cane, Derek Austyn, Merv Kenny, Fred Waldez), each with a distinct `color`.
- Prepare 15 tasks using `dyndatetime` offsets spread across today-1, today, and today+1. Each task has a single `resource` ID. Store them as the initial (unmodified) event array.
- Represent the current user as an object with `id`, `name`, and `role` (`'full'` / `'limited'` / `'readonly'`). The demo hard-codes Willis Cane with `role: 'limited'` as the default logged-in user.
- **Run the login simulation on mount.** It works on shallow copies of the event and resource arrays to avoid mutating the originals, then applies role logic:
  - **`'readonly'`**: Set `editable: false` and `color: '#af2ec3'` on every event.
  - **`'limited'`**: For each event, if `task.resource !== user.id` set `editable: false` and `color: '#6a6a6a'`; otherwise set `color: '#af2424'` (the user's own color). For each resource other than the user's own, set `eventCreation: false` to block creating events on foreign rows.
  - **`'full'`**: Leave all events and resources unmodified.
- Derive an `editEvents` boolean: `true` for `'full'` and `'limited'`, `false` for `'readonly'`. Pass this single value to `clickToCreate`, `dragToCreate`, `dragToMove`, `dragToResize`, and `eventDelete` simultaneously.
- Pass `extendDefaultEvent` returning `{ color: defaultColor }` where `defaultColor` is `'#af2424'` for `'limited'` and `''` for the other roles. This ensures newly drag-created events inherit the user's own color in limited mode.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-angular.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config angular
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   ng serve
   ```

On a trial, add `--trial` to the config command: `mobiscroll config angular --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/angular/getting-started/installation

## Related demos

- Previous: [External Date Navigation](https://demo.mobiscroll.com/angular/timeline/navigate-view-from-external-calendar.md) - Use a two-panel Angular Timeline navigated by an external date picker — selecting a date syncs the timeline and the picker instantly.
