Overview
The OrderList component displays a list of items that can be reordered using drag-and-drop or button controls. It’s ideal for managing priorities, sequences, or any ordered collection of items.
Import
import { MagaryOrderList } from 'ng-magary';
Basic Usage
import { Component, signal } from '@angular/core';
import { MagaryOrderList } from 'ng-magary';
@Component({
selector: 'app-orderlist-demo',
standalone: true,
imports: [MagaryOrderList],
template: `
<magary-order-list
[(value)]="items"
header="Task Priority"
[dragDrop]="true"
(onReorder)="onReorder($event)">
</magary-order-list>
`
})
export class OrderListDemoComponent {
items = signal([
{ id: 1, label: 'High Priority Task', status: 'urgent' },
{ id: 2, label: 'Medium Priority Task', status: 'normal' },
{ id: 3, label: 'Low Priority Task', status: 'low' }
]);
onReorder(reorderedItems: any[]) {
console.log('New order:', reorderedItems);
}
}
With Custom Item Template
<magary-order-list
[(value)]="tasks"
header="My Tasks"
[dragDrop]="true"
[showControls]="true">
<ng-template #itemTemplate let-task>
<div class="task-item">
<div class="flex items-center gap-3">
<i class="icon-{{ task.icon }}"></i>
<div class="flex-1">
<h4 class="font-semibold">{{ task.label }}</h4>
<p class="text-sm text-gray-600">{{ task.description }}</p>
</div>
<span class="badge" [class]="task.priority">
{{ task.priority }}
</span>
</div>
</div>
</ng-template>
</magary-order-list>
With Selection
@Component({
template: `
<magary-order-list
[(value)]="items"
[(selection)]="selectedItems"
header="Items"
[dragDrop]="true"
[showControls]="true"
(onSelectionChange)="onSelectionChange($event)">
</magary-order-list>
<div class="mt-4">
<p>Selected: {{ selectedItems().length }} items</p>
</div>
`
})
export class OrderListSelectionComponent {
items = signal([...]);
selectedItems = signal([]);
onSelectionChange(selected: any[]) {
console.log('Selection changed:', selected);
}
}
Properties
Array of items in the list. This is a model property supporting two-way binding.
Array of selected items. This is a model property supporting two-way binding.
Header text to display above the list.
listStyle
Record<string, string | number> | null
default:"null"
Inline styles to apply to the list container.
Enables drag-and-drop functionality for reordering items.
Whether to show the reorder control buttons (move up, down, top, bottom).
Events
Emitted when items are reordered. Contains the new ordered array.
Emitted when the selection changes. Contains the array of selected items.
Item Template
Customize item rendering:
<magary-order-list [(value)]="items">
<ng-template #itemTemplate let-item>
<div class="custom-item">
<span>{{ item.label }}</span>
<span class="badge">{{ item.category }}</span>
</div>
</ng-template>
</magary-order-list>
When showControls is true, four buttons are available:
- Move to Top: Move selected items to the beginning
- Move Up: Move selected items up one position
- Move Down: Move selected items down one position
- Move to Bottom: Move selected items to the end
Selection Behavior
Items can be selected by:
- Click: Single selection (or deselect if already selected)
- Ctrl/Cmd + Click: Toggle selection for multiple items
- Selected items can be moved together using control buttons
Drag and Drop
When dragDrop is enabled:
- Drag items to reorder them
- Drop between items to insert at position
- Visual feedback during drag operations
- Powered by Atlassian’s Pragmatic Drag and Drop
Advanced Example
import { Component, signal } from '@angular/core';
interface Task {
id: number;
label: string;
description: string;
priority: 'high' | 'medium' | 'low';
assignee?: string;
dueDate?: Date;
completed: boolean;
}
@Component({
template: `
<div class="orderlist-container">
<div class="flex justify-between items-center mb-4">
<h2>Task Priority Queue</h2>
<button (click)="addTask()" class="btn btn-primary">Add Task</button>
</div>
<magary-order-list
[(value)]="tasks"
[(selection)]="selectedTasks"
header="Tasks ({{ tasks().length }})"
[listStyle]="{ height: '600px' }"
[dragDrop]="true"
[showControls]="true"
(onReorder)="onTaskReorder($event)"
(onSelectionChange)="onSelectionChange($event)">
<ng-template #itemTemplate let-task>
<div class="task-card" [class.completed]="task.completed">
<div class="task-header">
<input
type="checkbox"
[checked]="task.completed"
(change)="toggleComplete(task)" />
<h4>{{ task.label }}</h4>
<span class="priority-badge" [class]="'priority-' + task.priority">
{{ task.priority }}
</span>
</div>
<p class="task-description">{{ task.description }}</p>
<div class="task-footer">
@if (task.assignee) {
<span class="assignee">👤 {{ task.assignee }}</span>
}
@if (task.dueDate) {
<span class="due-date">📅 {{ task.dueDate | date:'short' }}</span>
}
</div>
</div>
</ng-template>
</magary-order-list>
<div class="selection-info">
@if (selectedTasks().length > 0) {
<div class="flex gap-2">
<button (click)="deleteSelected()" class="btn btn-danger">
Delete Selected ({{ selectedTasks().length }})
</button>
<button (click)="markSelectedComplete()" class="btn btn-success">
Mark Complete
</button>
</div>
}
</div>
</div>
`,
styles: [`
.task-card {
padding: 1rem;
background: white;
border-radius: 0.5rem;
border: 1px solid #e5e7eb;
}
.task-card.completed {
opacity: 0.6;
text-decoration: line-through;
}
.priority-badge {
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.75rem;
font-weight: 600;
}
.priority-high {
background: #fee2e2;
color: #991b1b;
}
.priority-medium {
background: #fef3c7;
color: #92400e;
}
.priority-low {
background: #dbeafe;
color: #1e40af;
}
`]
})
export class TaskOrderListComponent {
tasks = signal<Task[]>([...]);
selectedTasks = signal<Task[]>([]);
onTaskReorder(reorderedTasks: Task[]) {
console.log('Tasks reordered');
this.updateTaskPriorities(reorderedTasks);
}
onSelectionChange(selected: Task[]) {
console.log('Selected tasks:', selected.length);
}
toggleComplete(task: Task) {
const tasks = this.tasks();
const index = tasks.findIndex(t => t.id === task.id);
if (index !== -1) {
tasks[index].completed = !tasks[index].completed;
this.tasks.set([...tasks]);
}
}
deleteSelected() {
const selected = this.selectedTasks();
const tasks = this.tasks().filter(t => !selected.includes(t));
this.tasks.set(tasks);
this.selectedTasks.set([]);
}
markSelectedComplete() {
const selected = this.selectedTasks();
const tasks = this.tasks().map(t =>
selected.includes(t) ? { ...t, completed: true } : t
);
this.tasks.set(tasks);
}
updateTaskPriorities(tasks: Task[]) {
// Update backend with new order
}
addTask() {
// Add new task
}
}
Styling
Key CSS classes:
magary-order-list - Main container
orderlist-header - Header section
orderlist-controls - Control buttons container
orderlist-list - List element
orderlist-item - Individual item
orderlist-item-selected - Selected item
orderlist-item-dragging - Item being dragged
orderlist-item-over - Drop target indicator
Custom Styling Example
.magary-order-list {
border: 1px solid var(--surface-border);
border-radius: 0.5rem;
overflow: hidden;
}
.orderlist-header {
background: var(--surface-100);
padding: 1rem;
font-weight: 600;
border-bottom: 1px solid var(--surface-border);
}
.orderlist-item {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--surface-border);
cursor: move;
transition: background 0.2s;
}
.orderlist-item:hover {
background: var(--surface-50);
}
.orderlist-item-selected {
background: var(--primary-50);
border-left: 3px solid var(--primary-color);
}
Use Cases
- Task Prioritization: Order tasks by priority
- Playlist Management: Reorder songs in a playlist
- Menu Ordering: Arrange menu items
- Feature Ranking: Rank features by importance
- Step Sequencing: Define step order in a process
Accessibility
- Keyboard navigation with Tab and Arrow keys
- Enter/Space to select items
- ARIA labels for controls and list
- Focus management during drag operations
- Screen reader announcements for reorder operations
The component uses Angular signals and OnPush change detection for optimal performance. The reorder utility from Pragmatic Drag and Drop ensures efficient list updates.
Source
View source: projects/ng-magary/src/lib/Data/orderlist/orderlist.ts:47