COMPONENT USAGE

Ecosistema completo para organización y gestión de contenido con interfaces espaciales

User Management Components - Usage Guide

Complete guide for using the user-management module components in your Angular 20 application.

Table of Contents

Installation

// In your app routes or feature module
import { userManagementRoutes } from '@libs-core/user-management';

export const routes: Routes = [
  {
    path: 'users',
    loadChildren: () => userManagementRoutes,
    canActivate: [authGuard],
  },
];

Components Overview

1. UserListComponent

Displays a paginated, filterable list of users with bulk operations.

Selector: lib-user-list

Features:

Usage:

import { UserListComponent } from '@libs-core/user-management';

@Component({
  standalone: true,
  imports: [UserListComponent],
  template: `<lib-user-list />`
})
export class UsersPageComponent {}

Inputs: None (uses NGXS state)

Outputs: None (uses NGXS actions)

Example with Custom Container:

@Component({
  template: `
    <div class="users-container">
      <h1>User Management</h1>
      <lib-user-list />
    </div>
  `
})
export class UsersPageComponent {}

2. UserDetailComponent

Shows detailed information about a specific user.

Selector: lib-user-detail

Features:

Usage:

import { UserDetailComponent } from '@libs-core/user-management';

@Component({
  standalone: true,
  imports: [UserDetailComponent],
  template: `<lib-user-detail />`
})
export class UserProfileComponent {}

Route Integration:

{
  path: 'users/:id',
  component: UserDetailComponent,
  canActivate: [authGuard, permissionGuard('users:read')]
}

3. UserFormComponent

Form for creating and editing users with validation.

Selector: lib-user-form

Features:

Usage:

import { UserFormComponent } from '@libs-core/user-management';

@Component({
  standalone: true,
  imports: [UserFormComponent],
  template: `
    <lib-user-form
      [mode]="mode()"
      (submitted)="handleSubmit($event)"
      (cancelled)="handleCancel()" />
  `
})
export class CreateUserComponent {
  mode = signal<'create' | 'edit'>('create');

  handleSubmit(user: CreateUserRequest) {
    console.log('User created:', user);
  }

  handleCancel() {
    console.log('Form cancelled');
  }
}

Inputs:

Outputs:


4. UserCardComponent

Compact user display card with actions.

Selector: lib-user-card

Features:

Usage:

import { UserCardComponent } from '@libs-core/user-management';

@Component({
  template: `
    @for (user of users(); track user.id) {
      <lib-user-card
        [user]="user"
        (viewDetails)="viewUser($event)"
        (edit)="editUser($event)"
        (delete)="deleteUser($event)" />
    }
  `
})
export class UserGridComponent {
  users = signal<User[]>([]);

  viewUser(userId: string) {
    this.router.navigate(['/users', userId]);
  }

  editUser(userId: string) {
    this.router.navigate(['/users', userId, 'edit']);
  }

  deleteUser(userId: string) {
    // Handle delete
  }
}

Inputs:

Outputs:


5. UserAvatarComponent

User avatar with fallback to initials.

Selector: lib-user-avatar

Features:

Usage:

import { UserAvatarComponent } from '@libs-core/user-management';

@Component({
  template: `
    <lib-user-avatar
      [user]="user()"
      [size]="'large'"
      [showStatus]="true" />
  `
})
export class ProfileHeaderComponent {
  user = signal<User | null>(null);
}

Inputs:

Sizes:


6. UserFilterComponent

Advanced filtering UI for user lists.

Selector: lib-user-filter

Features:

Usage:

import { UserFilterComponent } from '@libs-core/user-management';

@Component({
  template: `
    <lib-user-filter
      [filters]="currentFilters()"
      (filtersChanged)="applyFilters($event)"
      (reset)="resetFilters()" />
  `
})
export class UserSearchComponent {
  currentFilters = signal<UserFilters>({});

  applyFilters(filters: UserFilters) {
    this.currentFilters.set(filters);
    this.store.dispatch(new SetFilters(filters));
  }

  resetFilters() {
    this.currentFilters.set({});
    this.store.dispatch(new ClearFilters());
  }
}

Inputs:

Outputs:

Filter Options:

interface UserFilters {
  search?: string;                    // Name, email, username
  status?: UserStatus[];              // active, inactive, suspended, pending
  roleIds?: string[];                 // Role IDs
  createdAfter?: string;              // ISO date string
  createdBefore?: string;             // ISO date string
  lastActiveAfter?: string;           // ISO date string
  advancedFilters?: AdvancedFilter[]; // Custom filters
}

7. UserStatusBadgeComponent

Displays user status with color coding.

Selector: lib-user-status-badge

Features:

Usage:

import { UserStatusBadgeComponent } from '@libs-core/user-management';

@Component({
  template: `
    <lib-user-status-badge
      [status]="user().status"
      [lastActive]="user().lastActive" />
  `
})
export class UserStatusComponent {
  user = signal<User>({...});
}

Inputs:

Status Colors:


8. UserRoleManagerComponent

Role assignment and management UI.

Selector: lib-user-role-manager

Features:

Usage:

import { UserRoleManagerComponent } from '@libs-core/user-management';

@Component({
  template: `
    <lib-user-role-manager
      [user]="user()"
      [availableRoles]="availableRoles()"
      [readonly]="!canEditRoles()"
      (rolesChanged)="handleRolesChanged($event)"
      (primaryRoleChanged)="handlePrimaryRoleChanged($event)" />
  `
})
export class EditUserRolesComponent {
  user = signal<User>({...});
  availableRoles = signal<SystemRoles[]>([
    SystemRoles.ADMIN,
    SystemRoles.MANAGER,
    SystemRoles.USER,
    SystemRoles.VIEWER,
  ]);
  canEditRoles = signal(true);

  handleRolesChanged(roleIds: string[]) {
    console.log('Roles changed:', roleIds);
    // Update user roles
  }

  handlePrimaryRoleChanged(primaryRole: SystemRoles) {
    console.log('Primary role changed:', primaryRole);
    // Update primary role
  }
}

Inputs:

Outputs:

Role Hierarchy:

  1. ADMIN (Level 4) - Full administrative access
  2. MANAGER (Level 3) - Team and resource management
  3. USER (Level 2) - Standard user access
  4. VIEWER (Level 1) - Read-only access

State Management

All components integrate with NGXS state. Here's how to dispatch actions and select data:

Dispatching Actions

import { Store } from '@ngxs/store';
import * as UserActions from '@libs-core/user-management';

export class MyComponent {
  private store = inject(Store);

  loadUsers() {
    this.store.dispatch(new UserActions.LoadUsers());
  }

  createUser(request: CreateUserRequest) {
    this.store.dispatch(new UserActions.CreateUser(request));
  }

  updateUser(request: UpdateUserRequest) {
    this.store.dispatch(new UserActions.UpdateUser(request));
  }

  deleteUser(userId: string) {
    this.store.dispatch(new UserActions.DeleteUser(userId));
  }

  selectUser(user: User) {
    this.store.dispatch(new UserActions.SelectUser(user));
  }

  setFilters(filters: UserFilters) {
    this.store.dispatch(new UserActions.SetFilters(filters));
  }

  bulkUpdate(request: BulkOperationRequest) {
    this.store.dispatch(new UserActions.BulkUpdateUsers(request));
  }
}

Selecting State

import { UserState } from '@libs-core/user-management';

export class MyComponent {
  private store = inject(Store);

  users$ = this.store.select(UserState.getUsers);
  selectedUser$ = this.store.select(UserState.getSelectedUser);
  loading$ = this.store.select(UserState.isLoading);
  error$ = this.store.select(UserState.getError);
  filters$ = this.store.select(UserState.getFilters);
  bulkSelection$ = this.store.select(UserState.getBulkSelection);
  total$ = this.store.select(UserState.getTotal);
}

Using Signals with NGXS

import { toSignal } from '@angular/core/rxjs-interop';

export class MyComponent {
  private store = inject(Store);

  users = toSignal(this.store.select(UserState.getUsers), { initialValue: [] });
  loading = toSignal(this.store.select(UserState.isLoading), { initialValue: false });
  error = toSignal(this.store.select(UserState.getError), { initialValue: null });
}

Events Integration

Subscribe to domain events for cross-module coordination:

import { EventBusService } from '@libs-core/event-system';
import {
  UserCreatedEvent,
  UserUpdatedEvent,
  UserDeletedEvent
} from '@libs-core/user-management';

export class NotificationService {
  private eventBus = inject(EventBusService);

  constructor() {
    this.subscribeToUserEvents();
  }

  private subscribeToUserEvents() {
    // User created
    this.eventBus.subscribe(UserCreatedEvent, (event) => {
      console.log('User created:', event.payload.user);
      this.showNotification(`New user ${event.payload.user.email} created`);
    });

    // User updated
    this.eventBus.subscribe(UserUpdatedEvent, (event) => {
      console.log('User updated:', event.payload.user);
      this.showNotification(`User ${event.payload.user.email} updated`);
    });

    // User deleted
    this.eventBus.subscribe(UserDeletedEvent, (event) => {
      console.log('User deleted:', event.payload.userId);
      this.showNotification(`User deleted`);
    });
  }

  private showNotification(message: string) {
    // Show notification to user
  }
}

Security & Permissions

Route Protection

import { authGuard, permissionGuard, roleGuard } from '@libs-core/security';
import { SystemRoles } from '@libs-core/shared-models';

export const routes: Routes = [
  {
    path: 'users',
    canActivate: [authGuard],
    children: [
      {
        path: '',
        component: UserListComponent,
        canActivate: [permissionGuard('users:read')],
      },
      {
        path: 'create',
        component: UserFormComponent,
        canActivate: [permissionGuard('users:create')],
      },
      {
        path: ':id/edit',
        component: UserFormComponent,
        canActivate: [permissionGuard('users:update')],
      },
      {
        path: 'admin',
        component: UserListComponent,
        canActivate: [
          roleGuard(SystemRoles.ADMIN),
          permissionGuard('users:manage'),
        ],
      },
    ],
  },
];

Permission Checks in Components

import { PermissionService } from '@libs-core/security';

export class UserActionsComponent {
  private permissionService = inject(PermissionService);

  canCreate = this.permissionService.hasPermission('users:create');
  canUpdate = this.permissionService.hasPermission('users:update');
  canDelete = this.permissionService.hasPermission('users:delete');
  canManage = this.permissionService.hasPermission('users:manage');
}

Multi-Tenant Context

All operations automatically use tenant context from ContextService:

import { ContextService } from '@libs-core/security';

export class UserService {
  private contextService = inject(ContextService);

  getCurrentTenant() {
    const context = this.contextService.getCurrentContext();
    return context.tenantId; // Used automatically in all API calls
  }
}

Best Practices

1. Use Standalone Components

All components are standalone - import directly where needed:

import { UserListComponent } from '@libs-core/user-management';

@Component({
  standalone: true,
  imports: [UserListComponent],
  // ...
})

2. Leverage Signals

Use Angular signals for reactive data:

export class UserComponent {
  users = toSignal(this.store.select(UserState.getUsers));

  filteredUsers = computed(() => {
    return this.users().filter(u => u.status === 'active');
  });
}

3. Handle Errors Gracefully

export class UserComponent {
  error = toSignal(this.store.select(UserState.getError));

  ngOnInit() {
    effect(() => {
      const errorMessage = this.error();
      if (errorMessage) {
        this.showErrorNotification(errorMessage);
      }
    });
  }
}

4. Clean Up Subscriptions

Event subscriptions are automatically cleaned up, but for custom observables:

export class UserComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  ngOnInit() {
    this.customObservable$
      .pipe(takeUntil(this.destroy$))
      .subscribe(/*...*/);
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

5. Use OnPush Change Detection

All components use OnPush - ensure immutability:

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  // ...
})
export class UserComponent {
  updateUser(user: User) {
    // Create new object instead of mutating
    const updated = { ...user, firstName: 'New Name' };
    this.store.dispatch(new UpdateUser(updated));
  }
}

Styling & Theming

Components use CSS variables for easy theming:

:root {
  /* Primary colors */
  --primary-color: #3b82f6;
  --primary-hover: #2563eb;

  /* Status colors */
  --status-active: #059669;
  --status-inactive: #6b7280;
  --status-suspended: #dc2626;
  --status-pending: #f59e0b;

  /* Role colors */
  --role-admin-bg: #dc2626;
  --role-manager-bg: #2563eb;
  --role-user-bg: #059669;
  --role-viewer-bg: #6b7280;

  /* Spacing */
  --spacing-xs: 0.25rem;
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 1.5rem;
  --spacing-xl: 2rem;
}

Accessibility

All components follow WCAG 2.1 Level AA:

Example:

<!-- UserCardComponent template -->
<article
  role="article"
  aria-label="User card for John Doe"
  tabindex="0">
  <!-- Content -->
</article>

Troubleshooting

Component Not Rendering

Check that you've imported the component:

import { UserListComponent } from '@libs-core/user-management';

@Component({
  imports: [UserListComponent], // Must be in imports array
})

State Not Updating

Ensure NGXS is configured in your app:

import { provideStore } from '@ngxs/store';
import { UserState } from '@libs-core/user-management';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore([UserState]),
    // ...
  ],
};

Events Not Firing

Verify EventBusService is provided:

import { provideEventSystem } from '@libs-core/event-system';

export const appConfig: ApplicationConfig = {
  providers: [
    provideEventSystem(),
    // ...
  ],
};

Support

For issues, feature requests, or questions, please refer to: