Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
calendar component angular 4
<div class="calendar">
<div class="calendar-navs">
<div class="month-nav">
<button (click)="prevMonth()">&lt;</button>
<span class="p4">{{ currentDate.format('MMMM') }}</span>
<button (click)="nextMonth()">&gt;</button>
</div>
<div class="year-nav">
<button (click)="prevYear()">&lt;</button>
<span>{{ currentDate.format('YYYY') }}</span>
<button (click)="nextYear()">&gt;</button>
</div>
</div>
<div class="month-grid">
<div class="day-names">
<div *ngFor="let name of dayNames" class="day-name p9">
{{ name }}
</div>
</div>
<div class="weeks">
<div *ngFor="let week of weeks" class="week">
<ng-container *ngFor="let day of week">
<div class="week-date disabled" *ngIf="!isSelectedMonth(day.mDate)">
<span class="date-text">{{ day.mDate.date() }}</span>
</div>
<div class="week-date enabled"
*ngIf="isSelectedMonth(day.mDate)"
(click)="selectDate(day)"
[ngClass]="{ today: day.today, selected: day.selected }">
<span class="date-text">{{ day.mDate.date() }}</span>
</div>
</ng-container>
</div>
</div>
</div>
</div>
@import '../../styles/vars.scss';
@import '../../styles/typography.scss';
@import '../../styles/colors.scss';
$dayBase: 30px;
.calendar {
display: block;
width: $dayBase * 7;
margin: 0 auto;
* {
box-sizing: border-box;
}
.calendar-navs {
background-color: $cloud;
}
.month-nav {
padding: $base;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.year-nav {
padding: $base;
display: flex;
flex-direction: row;
justify-content: space-between;
font-family: 'Montserrat';
}
.month-grid {
.day-names {
display: flex;
flex-direction: row;
background: $concrete;
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
}
.weeks {
display: flex;
flex-direction: column;
}
.week {
display: flex;
flex-direction: row;
}
.week-date,
.day-name {
text-align: center;
padding: $base;
display: block;
width: $dayBase;
display: flex;
justify-content: center;
align-items: center;
}
.week-date {
height: $dayBase;
position: relative;
.date-text {
z-index: 10;
font-size: 10px;
font-family: 'Montserrat', sans-serif;
}
&::after {
content: '';
height: $dayBase * 0.9;
width: $dayBase * 0.9;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
transition: background-color 150ms linear, color 150ms linear;
z-index: 1;
}
&.enabled {
cursor: pointer;
&:hover {
&:after {
background-color: $seafoam;
}
}
}
&.selected {
color: $white;
&:after {
background-color: $teal;
}
&:hover {
&:after {
background-color: $teal;
}
}
}
&.disabled {
color: $light-blue-grey;
}
}
.today {
font-weight: bold;
}
}
}
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import * as moment from 'moment';
import { CalendarComponent, CalendarDate } from './calendar.component';
describe('CalendarComponent', () => {
let component: CalendarComponent;
let fixture: ComponentFixture<CalendarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CalendarComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CalendarComponent);
component = fixture.componentInstance;
});
describe('Select date', () => {
it ('should emit date when selected', () => {
let selectedDate: CalendarDate = {
selected: false,
today: false,
inRange: false,
mDate: moment()
};
component.onSelectDate.subscribe(x => selectedDate = x);
component.selectDate(selectedDate);
const isSame = moment(selectedDate.mDate).isSame(moment(selectedDate.mDate), 'day');
expect(isSame).toBeTruthy();
});
});
describe('Calendar grid generation', () => {
it('should generate 6 weeks', () => {
component.generateCalendar();
fixture.detectChanges();
expect(component.weeks.length).toEqual(6);
});
it('should generate Feb 2017 correctly', () => {
component.currentDate = moment('2017-02-05');
component.generateCalendar();
fixture.detectChanges();
expect(component.weeks[0][0].mDate.date()).toEqual(29);
expect(component.weeks[5][6].mDate.date()).toEqual(11);
});
});
describe('Year navigation', () => {
it('should go forward 1 year', () => {
component.currentDate = moment('2017-09-10');
fixture.detectChanges();
component.nextYear();
fixture.detectChanges();
expect(component.currentDate.year()).toEqual(2018);
});
it('should go backward 1 year', () => {
component.currentDate = moment('2017-09-10');
fixture.detectChanges();
component.prevYear();
fixture.detectChanges();
expect(component.currentDate.year()).toEqual(2016);
});
});
describe('Month navigation', () => {
it('should go forward 1', () => {
component.currentDate = moment('2017-09-10');
fixture.detectChanges();
component.nextMonth();
fixture.detectChanges();
expect(component.currentDate.month()).toEqual(9);
});
it('should go backward 1', () => {
component.currentDate = moment('2017-09-10');
fixture.detectChanges();
component.prevMonth();
fixture.detectChanges();
expect(component.currentDate.month()).toEqual(7);
});
it('should go to january', () => {
component.currentDate = moment('2017-09-10');
fixture.detectChanges();
component.firstMonth();
fixture.detectChanges();
expect(component.currentDate.month()).toEqual(0);
});
it('should go to december', () => {
component.currentDate = moment('2017-09-10');
fixture.detectChanges();
component.lastMonth();
fixture.detectChanges();
expect(component.currentDate.month()).toEqual(11);
});
});
});
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import * as moment from 'moment';
import * as _ from 'lodash';
export interface CalendarDate {
mDate: moment.Moment;
selected?: boolean;
today?: boolean;
}
@Component({
selector: 'yoshimi-calendar',
templateUrl: './calendar.component.html',
})
export class CalendarComponent implements OnInit, OnChanges {
currentDate = moment();
dayNames = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
weeks: CalendarDate[][] = [];
sortedDates: CalendarDate[] = [];
@Input() selectedDates: CalendarDate[] = [];
@Output() onSelectDate = new EventEmitter<CalendarDate>();
constructor() {}
ngOnInit(): void {
this.generateCalendar();
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.selectedDates &&
changes.selectedDates.currentValue &&
changes.selectedDates.currentValue.length > 1) {
// sort on date changes for better performance when range checking
this.sortedDates = _.sortBy(changes.selectedDates.currentValue, (m: CalendarDate) => m.mDate.valueOf());
this.generateCalendar();
}
}
// date checkers
isToday(date: moment.Moment): boolean {
return moment().isSame(moment(date), 'day');
}
isSelected(date: moment.Moment): boolean {
return _.findIndex(this.selectedDates, (selectedDate) => {
return moment(date).isSame(selectedDate.mDate, 'day');
}) > -1;
}
isSelectedMonth(date: moment.Moment): boolean {
return moment(date).isSame(this.currentDate, 'month');
}
selectDate(date: CalendarDate): void {
this.onSelectDate.emit(date);
}
// actions from calendar
prevMonth(): void {
this.currentDate = moment(this.currentDate).subtract(1, 'months');
this.generateCalendar();
}
nextMonth(): void {
this.currentDate = moment(this.currentDate).add(1, 'months');
this.generateCalendar();
}
firstMonth(): void {
this.currentDate = moment(this.currentDate).startOf('year');
this.generateCalendar();
}
lastMonth(): void {
this.currentDate = moment(this.currentDate).endOf('year');
this.generateCalendar();
}
prevYear(): void {
this.currentDate = moment(this.currentDate).subtract(1, 'year');
this.generateCalendar();
}
nextYear(): void {
this.currentDate = moment(this.currentDate).add(1, 'year');
this.generateCalendar();
}
// generate the calendar grid
generateCalendar(): void {
const dates = this.fillDates(this.currentDate);
const weeks: CalendarDate[][] = [];
while (dates.length > 0) {
weeks.push(dates.splice(0, 7));
}
this.weeks = weeks;
}
fillDates(currentMoment: moment.Moment): CalendarDate[] {
const firstOfMonth = moment(currentMoment).startOf('month').day();
const firstDayOfGrid = moment(currentMoment).startOf('month').subtract(firstOfMonth, 'days');
const start = firstDayOfGrid.date();
return _.range(start, start + 42)
.map((date: number): CalendarDate => {
const d = moment(firstDayOfGrid).date(date);
return {
today: this.isToday(d),
selected: this.isSelected(d),
mDate: d,
};
});
}
}
@karocksjoelee

This comment has been minimized.

Copy link

commented Aug 1, 2018

could you provide your :

@import '../../styles/vars.scss';
@import '../../styles/typography.scss';
@import '../../styles/colors.scss';

Thx ~

@jitenderbadoni

This comment has been minimized.

Copy link

commented Sep 30, 2018

$dayBase: 30px;
$cloud:'#ccc';
$base:5px;
$concrete:'#fff';
$seafoam:'blue';
$white:'#fff';
$teal:'black';
$light-blue-grey:'#888';

declare all variables above and use based on your theme.!

@BerezkinBerezkin

This comment has been minimized.

Copy link

commented Nov 22, 2018

how to add each week its order number in the year?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.