this.hostElement는 템플릿 내용을 렌더링 하려는 엘리먼트에 대한 참조를 보유하는 것.
this.templateElement는 이 내용을 보유하는 템플릿에 대한 접근성을 제공한다.
this.templateElement = document.getElementById('project-input')
으로 접근할 수 있다.
오류가 발생하는데 이를 해결하기 위해
templateElement: HTMLTemplateElement;
를 클래스에 직접 추가한다. 저장될 타입은 HTMLTemplateElement로 명확히 한다. 이 타입은 전역에서 사용할 수 있다. lib에 dom을 추가하였기 때문.
타입스크립트는 html파일을 분석하지 않기 때문에 값이 null이 될 수 있다는 오류가 발생. 느낌표를 추가하여 null값이 들어오지 않을거라고 타입스크립트에게 알려줄 수 있다
this.templateElement = document.getElementById('project-input')!;
혹은 변수를 생성하여 조건문을 작성하고 null이 아니라면 의 내요을 작성해준다.
혹은 타입 캐스팅을 활용하여
this.templateElement = <HTMLTemplateElement>document.getElementById('project-input')!;
를 작성하여 해결한다.
혹은
this.templateElement = document.getElementById('project-input')! as HTMLTemplateElement;
로 해결한다.
이러한 방법들로 여기에 가져오는 것이 null아니고 특정한 타입이 될 것이라고 말해줄 수 있다.
hostElement도 작성해주어야 하는데 index.html의
를 렌더링 해야한다.그러므로 클래스에
hostElement: HTMLDivElement;
를 작성해준다.
같은 식으로 작성하면
this.hostElement = document.getElementById('app');
이전과 똑같은 문제인 null 값이 될 수 있다는 오류가 발생
!와 as로 해결해준다.
this.hostElement = document.getElementById('app')! as HTMLDivElement;
이제 이 엘리먼트들에 접근할 수 있지만 아무것도 렌더링 할 수 없다. 이를 위해 templateElement의 내용을 가져와야 한다
템플릿 태그 안에 있는것을 가져와서 이것을 dom에 렌더링한다.
constructor에
const importedNode = document.importNode();
를 작성하는데 이 메서드는 전역 문서 객체에 제공되는 메서드이다.
constructor에
const importedNode = document.importNode(this.templateElement.content);
인자에는 내용을 전달해야 하기 때문에 .content를 명확히 전달하자. 두번째 인자에는 깊은복사를 통해 가져올 것인지 nest 수준으로 가져올 것인지 정한다. 깊은복사로 작성(true)
constructor에
const importedNode = document.importNode(this.templateElement.content, true);
importedNode의 타입은 타입스크립트가 추론하였다. 이제 이것을 이용해서 콘텐츠를 렌더링할 수 있다.
이를 위해 새로운 메서드를 입력한다.
private attach() {
this.hostElement.insertAdjacentElement('afterbegin');
}
}
이것은 HTMLElement를 삽입하기 위해 자바스크립트 브라우저에서 제공하는 기본 메서드이다.
afterbegin을 작성하여 여는 태그가 바로 시작되는 곳에 삽입
두번쨰 인자는 importedNode를 전달할건데, 이는 생성자에서만 사용할 수 있고 이것은 DocumentFragment라서 바로 삽입할 수 없다.
index.html 내용을 확인하여 이것이 form 내용이라는것을 확인 후
클래스에
element: HTMLFormElement;
를 추가하고
constructor에
this.element = importedNode.firstElementChild as HTMLFormElement;
라고 타입스크립트에 말해주고
private attach() {
this.hostElement.insertAdjacentElement('afterbegin', this.element);
}
}
두번째 인자로
this.element를 전달해주면 우리가 삽입하려는 노드를 가르키는 확실한 프로퍼티가 될 수 있다.
그 후 생성자에 attach 메서드도 호출하여 코드가 실행되도록 해야한다.
this.attach();
이제 모든 형식을 갖추었고 새로운 상수를 간단히 생성해보면
const prjInput = new ProjectInput();
컴파일 후 프라우저로 돌아가면 프로젝트 양식이 출력되어있다.
최종 코드
class ProjectInput {
templateElement: HTMLTemplateElement;
hostElement: HTMLDivElement;
element: HTMLFormElement;
constructor() {
this.templateElement = document.getElementById(
"project-input"
)! as HTMLTemplateElement;
this.hostElement = document.getElementById("app")! as HTMLDivElement;
const importedNode = document.importNode(
this.templateElement.content,
true
);
this.element = importedNode.firstElementChild as HTMLFormElement;
this.attach();
}
private attach() {
this.hostElement.insertAdjacentElement("afterbegin", this.element);
}
}
const prjInput = new ProjectInput();