PrimeNG是Angular生态中常用的UI组件库,其中的Calendar组件支持单选、多选、范围选择等多种日期选择模式,在多选模式下,默认组件会显示当前系统日期所在的月份,实际开发中经常需要根据业务规则动态调整显示的月份,比如根据关联的下拉框选择年份月份来切换Calendar的显示内容。

PrimeNG Calendar多选模式基础配置
首先需要在Angular项目中引入PrimeNG的CalendarModule,然后在模板中配置多选模式,核心是通过selectionMode属性设置为multiple,同时可以通过ngModel或者FormControl绑定选中的日期数组。
基础的多选模式模板代码如下:
<p-calendar [(ngModel)]="selectedDates" selectionMode="multiple" placeholder="选择多个日期" ></p-calendar>
对应的组件类基础代码:
import { Component } from '@angular/core';
@Component({
selector: 'app-calendar-demo',
templateUrl: './calendar-demo.component.html',
styleUrls: ['./calendar-demo.component.css']
})
export class CalendarDemoComponent {
// 存储选中的多个日期
selectedDates: Date[] = [];
}
动态控制显示月份的核心思路
PrimeNG Calendar组件提供了currentMonth和currentYear两个属性,分别用于设置当前显示的月份和年份,月份的取值范围是0到11,对应1月到12月。同时组件支持通过ViewChild获取实例,调用实例的updateViewDate方法可以更新显示的月份和年份。
方式一:通过属性绑定动态设置
可以直接在模板中绑定currentMonth和currentYear属性,当绑定的值发生变化时,Calendar会自动更新显示的月份。
模板代码示例:
<div class="control-area">
<label>选择显示年份:</label>
<input type="number" [(ngModel)]="displayYear" (ngModelChange)="updateDisplayMonth()" />
<label>选择显示月份:</label>
<select [(ngModel)]="displayMonth" (ngModelChange)="updateDisplayMonth()">
<option *ngFor="let month of monthOptions" [value]="month.value">
{{ month.label }}
</option>
</select>
</div>
<p-calendar
[(ngModel)]="selectedDates"
selectionMode="multiple"
[currentYear]="displayYear"
[currentMonth]="displayMonth"
placeholder="选择多个日期"
></p-calendar>
组件类代码:
import { Component } from '@angular/core';
@Component({
selector: 'app-calendar-demo',
templateUrl: './calendar-demo.component.html',
styleUrls: ['./calendar-demo.component.css']
})
export class CalendarDemoComponent {
selectedDates: Date[] = [];
// 显示的年份,默认当前年份
displayYear: number = new Date().getFullYear();
// 显示的月份,默认当前月份,0代表1月
displayMonth: number = new Date().getMonth();
// 月份选项,value是0-11对应1-12月
monthOptions = [
{ label: '1月', value: 0 },
{ label: '2月', value: 1 },
{ label: '3月', value: 2 },
{ label: '4月', value: 3 },
{ label: '5月', value: 4 },
{ label: '6月', value: 5 },
{ label: '7月', value: 6 },
{ label: '8月', value: 7 },
{ label: '9月', value: 8 },
{ label: '10月', value: 9 },
{ label: '11月', value: 10 },
{ label: '12月', value: 11 }
];
updateDisplayMonth() {
// 可以在这里添加年份和月份的合法性校验
if (this.displayYear < 1900 || this.displayYear > 2100) {
this.displayYear = new Date().getFullYear();
}
if (this.displayMonth < 0 || this.displayMonth > 11) {
this.displayMonth = new Date().getMonth();
}
}
}
方式二:通过组件实例方法更新
如果需要更灵活的控制,比如在某些业务逻辑执行后切换月份,可以通过ViewChild获取Calendar组件的实例,调用实例的updateViewDate方法更新显示的月份和年份。
模板代码:
<button (click)="switchToNextMonth()">切换到下个月</button> <p-calendar #calendar [(ngModel)]="selectedDates" selectionMode="multiple" placeholder="选择多个日期" ></p-calendar>
组件类代码:
import { Component, ViewChild } from '@angular/core';
import { Calendar } from 'primeng/calendar';
@Component({
selector: 'app-calendar-demo',
templateUrl: './calendar-demo.component.html',
styleUrls: ['./calendar-demo.component.css']
})
export class CalendarDemoComponent {
selectedDates: Date[] = [];
// 获取Calendar组件实例
@ViewChild('calendar') calendar!: Calendar;
switchToNextMonth() {
// 获取当前显示的年份和月份
let currentYear = this.calendar.currentYear;
let currentMonth = this.calendar.currentMonth;
// 计算下个月的年份和月份
if (currentMonth === 11) {
currentYear += 1;
currentMonth = 0;
} else {
currentMonth += 1;
}
// 调用方法更新显示的月份
this.calendar.updateViewDate(currentYear, currentMonth);
}
}
常见场景示例:根据关联值联动切换月份
实际开发中经常有需求是选择一个年份和月份后,Calendar自动切换到对应的月份显示,同时限制只能选择该月份的日期,结合之前的属性绑定方式可以很容易实现。
完整组件类代码:
import { Component } from '@angular/core';
@Component({
selector: 'app-calendar-demo',
templateUrl: './calendar-demo.component.html',
styleUrls: ['./calendar-demo.component.css']
})
export class CalendarDemoComponent {
selectedDates: Date[] = [];
displayYear: number = new Date().getFullYear();
displayMonth: number = new Date().getMonth();
monthOptions = [
{ label: '1月', value: 0 },
{ label: '2月', value: 1 },
{ label: '3月', value: 2 },
{ label: '4月', value: 3 },
{ label: '5月', value: 4 },
{ label: '6月', value: 5 },
{ label: '7月', value: 6 },
{ label: '8月', value: 7 },
{ label: '9月', value: 8 },
{ label: '10月', value: 9 },
{ label: '11月', value: 10 },
{ label: '12月', value: 11 }
];
// 年份月份变化时更新Calendar显示,同时限制可选日期范围
onDateRangeChange() {
// 设置可选日期的最小值和最大值,限制只能选当前显示的月份
const minDate = new Date(this.displayYear, this.displayMonth, 1);
const maxDate = new Date(this.displayYear, this.displayMonth + 1, 0);
// 如果之前选中的日期不在当前月份,清空选中值
this.selectedDates = this.selectedDates.filter(date => {
return date >= minDate && date <= maxDate;
});
}
}
对应的模板中给年份和月份的选择控件添加ngModelChange事件绑定onDateRangeChange方法即可实现联动效果。
注意事项
- Calendar的
currentMonth属性取值是0到11,对应1月到12月,设置的时候不要搞错取值范围。 - 如果同时设置了
minDate和maxDate属性,动态切换月份的时候需要确保设置的显示月份在可选日期范围内,否则组件可能不会正常显示。 - 通过
ViewChild获取组件实例的时候,需要确保组件已经初始化完成,避免在ngOnInit阶段调用实例方法导致报错。