我想在我的应用中创建自定义日历。在 JavaScript 中开发代码时,它可以正常工作。当我尝试将代码迁移到Angular 6之后,它无法正常工作。 Angular抛出运行时错误。我无法解决,
任何人都可以帮助我!
这是我正在使用的Stack-Blitz链接:StackBlitz!
showCalendar(month, year) {
const firstDay = (new Date(year, month)).getDay();
const daysInMonth = 32 - new Date(year, month, 32).getDate();
console.log('\n val \n' + new Date(year, month, 32).getDate());
const tbl = document.getElementById('calendar-body');
// clearing all previous cells
tbl.innerHTML = '';
// filing data about month and in the page via DOM.
this.monthAndYear.innerHTML = this.months[month] + ' ' + year;
// creating all cells
let date = 1;
for (let i = 0; i < 6; i++) {
const row = document.createElement('tr');
for (let j = 0; j < 7; j++) {
// let cell = document.createElement('td');
if (i === 0 && j < firstDay) {
const cell = document.createElement('td');
const cellText = document.createTextNode('');
cell.appendChild(cellText);
row.appendChild(cell);
} else if (date > daysInMonth) {
break;
} else {
const cell = document.createElement('td');
const cellText = document.createTextNode(date.toString());
if (date === this.today.getDate() && year === this.today.getFullYear() && month === this.today.getMonth()) {
// cell.classList.add("bg-info");
} // color todays date
date++;
}
}
tbl.appendChild(row); // appending each row into calendar body.
}
}
constructor() {
this.today = new Date();
this.currentMonth = this.today.getMonth();
this.currentYear = this.today.getFullYear();
this.monthAndYear = document.getElementById('monthAndYear');
}
ngOnInit() {
this.showCalendar(this.currentMonth, this.currentYear);
console.log('ngOnInit');
}
预期结果是显示日历。
但是它给出错误为:
ERROR TypeError: Cannot set property 'innerHTML' of null
at CustomCalendarComponent.push../src/app/components/custom-calendar/custom-calendar.component.ts.CustomCalendarComponent.showCalendar (custom-calendar.component.ts:67)
答案 0 :(得分:1)
将document.getElementByid('monthAndYear')
移动到ngOnInit,因为在调用构造函数时尚无附加的DOM。
https://stackblitz.com/edit/angular-yzzvsb?file=src/app/app.component.ts
此外,整个日历生成逻辑都已损坏,因此您必须对其进行处理。添加行和单元格。但是,为什么将它们设置为空是一个谜。
答案 1 :(得分:1)
Angular使用单独的API来操作DOM.Angular提供的Renderer2以一种服务的形式提供,该服务允许在不直接接触DOM的情况下操作应用程序的元素
如果要使用模板变量从DOM中选择特定元素,请使用ViewChild装饰器访问组件类中的元素
component.html
<h3 class="card-reader" id="monthAndYear" #monthAndYear> Month and Year</h3>
component.ts
@ViewChild('monthAndYear') monthAndYear: ElementRef;
使用Renderer2创建新元素
constructor(private ren: Renderer2) {}
const cell = this.ren.createElement('td');
const cellText = this.ren.createText('');
cell.appendChild(cellText);