전에 MVC패턴에서 View를 다시 한번 생각해보면 Model, Controller에 대해 알지 못하고 화면에 데이터를 저장을 하지 못하며 변경된 화면요소에 대한 처리를 위해 Controller에게 통보를 해야한다.
우선 InputView와 MainController을 연결하고 화면을 렌더링 해야한다.
class View는 해당 요소를 파라미터로 받아 화면을 구현한다.
import View from "./View.js";
export default class InputView extends View {
constructor() {
super();
this.tag = "[InputView]";
}
setup(el) {
this.init(el);
this.el.innerHTML = this.render();
return this;
}
render() {
//화면 구현
return ``;
}
}
class MainController는 화면을 구현할 요소를 InputView에 넘겨준다
import InputView from "../views/InputView.js";
export default class MainController {
constructor() {
this.tag = "[MainController]";
this._app = document.getElementById("app");
this.InputView = new InputView();
}
init() {
console.log(this.tag, "init()");
this.InputView.setup(this._app);
}
}
Template literals을 이용해 화면을 구현한다.
구현하기 앞서 DOM 요소의 ID값을 상수화 시켜서 사용한다.
utils/variables.js
export const DOM_ID = {
DEPARTURE_STATION_NAME_INPUT_ID: "departure-station-name-input",
ARRIVAL_STATION_NAME_INPUT_ID: "arrival-station-name-input",
SEARCH_BUTTON_ID: "search-button",
SHORTEST_DISTANCE_RADIO_ID: "shortest-distance-radio",
MINIMUM_DISTANCE_RADIO_ID: "minimum-distance-radio",
SEARCH_BUTTON_ID: "search-button",
SEARCH_TYPE_NAME: "search-type",
};
화면렌더링 InputView.js
import View from "./View.js";
import { DOM_ID } from "../utils/variables.js";
export default class InputView extends View {
constructor() {
super();
this.tag = "[InputView]";
}
setup(el) {
this.init(el);
this.el.innerHTML = this.render();
return this;
}
render() {
return this.headerText() + this.inputForm();
}
headerText() {
return `<h1>🚇 지하철 길찾기</h1>`;
}
inputForm() {
return `
<form>
${
this.inputDeparture() +
this.inputArrival() +
this.inputRadio() +
this.searchButton()
}
</form>
`;
}
inputDeparture() {
return `
<div>
<label for=${DOM_ID.DEPARTURE_STATION_NAME_INPUT_ID}>출발역</label>
<input
type="text"
id=${DOM_ID.DEPARTURE_STATION_NAME_INPUT_ID}
autocomplete="off"
/>
</div>
`;
}
inputArrival() {
return `
<div>
<label for=${DOM_ID.ARRIVAL_STATION_NAME_INPUT_ID}>도착역</label>
<input
type="text"
id=${DOM_ID.ARRIVAL_STATION_NAME_INPUT_ID}
autocomplete="off"
/>
</div>
`;
}
inputRadio() {
return `
<div>
<input
type="radio"
id=${DOM_ID.SHORTEST_DISTANCE_RADIO_ID}
name="search-type"
value="distance"
checked="checked"
/>
<label for=${DOM_ID.SHORTEST_DISTANCE_RADIO_ID}>최단거리</label>
<input
type="radio"
id=${DOM_ID.MINIMUM_DISTANCE_RADIO_ID}
name="search-type"
value="time"
/>
<label for=${DOM_ID.MINIMUM_DISTANCE_RADIO_ID}>최소거리</label>
</div>
`;
}
searchButton() {
return `
<div>
<button id=${DOM_ID.SEARCH_BUTTON_ID}>길 찾기</button>
</div>
`;
}
}
라디오 버튼 동적으로 속성 바꾸기
라디오 버튼을 클릭하면 MainController에서 해당 라디오의 id값을 InputView에 전달해서 checked속성을 준다.(radio option의 default값은 최단거리이다)
InputView.js
setup(el) {
this.init(el);
this.el.innerHTML = this.render();
this.bindEvents();
return this;
}
bindEvents() {
this.on("click", (e) => this.onClick(e));
}
changeRadio(changeRado_info) {
console.log(this.tag, "changeRadio()", changeRado_info);
changeRado_info.checkedRadio.setAttribute("checked", "checked");
changeRado_info.unCheckedRadio.removeAttribute("checked");
}
MainController.js
init() {
console.log(this.tag, "init()");
this.InputView.setup(this._app)
.on("@clickRadio", (e) => this.onClickRadio(e.detail.radio));
}
onClickRadio(radio) {
console.log(this.tag, "onClickRadio()", radio);
const radioIDError = new Error(`잘못된 radio id 값`);
if (radio.id === DOM_ID.SHORTEST_DISTANCE_RADIO_ID) {
return this.InputView.changeRadio({
checkedRadio: radio,
unCheckedRadio: document.getElementById(
DOM_ID.MINIMUM_DISTANCE_RADIO_ID
),
});
}
if (radio.id === DOM_ID.MINIMUM_DISTANCE_RADIO_ID) {
return this.InputView.changeRadio({
checkedRadio: radio,
unCheckedRadio: document.getElementById(
DOM_ID.SHORTEST_DISTANCE_RADIO_ID
),
});
}
throw radioIDError;
}
입력값 유효성 판단 & 최단경로 구하기(Dijkstra 라이브러리)
- 빈 값 입력 유무
- 존재하는 역 이름인지 판단
- 출발역과 도착역이 같은지 판단
- 출발역과 도착역이 연결되어 있는지 판단
onSubmit(input_info) {
console.log(this.tag, "onSubmit()", input_info);
const { departure, arrival, option } = input_info;
this.addEdgeSections(option);
if (!this.isValidInput(departure, arrival)) {
return;
}
let result = this.Dijkstra.findShortestPath(departure, arrival);
if (!this.isConnection(result)) {
return;
}
console.log(result);
}
addEdgeSections(option) {
sections.forEach((section_info) => {
this.Dijkstra.addEdge(
section_info.section_stations[0],
section_info.section_stations[1],
section_info[option]
);
});
}
isValidInput(departure, arrival) {
if (
this.isEmpty(departure, arrival) &&
this.isCorrectStationName(departure, arrival) &&
this.isSameStationName(departure, arrival)
) {
return true;
}
return false;
}
isEmpty(departure, arrival) {
if (departure === "" && arrival === "") {
alert("역 이름을 입력해주세요");
return false;
}
return true;
}
isCorrectStationName(departure, arrival) {
if (stations.includes(departure) && stations.includes(arrival)) {
return true;
}
alert("존재하지 않는 역 입니다.");
return false;
}
isSameStationName(departure, arrival) {
if (departure !== arrival) {
return true;
}
alert("같은 이름");
return false;
}
isConnection(result) {
if (result !== undefined) {
return true;
}
window.alert("연결되어 있지 않습니다.");
return false;
}
최단거리 최소거리 구하기
getEdge(start, end) {
const section = sections.find((section_info) => {
const sectionStations = section_info["section_stations"];
if (
(sectionStations[0] === start && sectionStations[1] === end) ||
(sectionStations[1] === start && sectionStations[0] === end)
) {
return {
distance: sectionStations.distance || 0,
time: sectionStations.time || 0,
};
}
});
return { ...section };
}
getTotalDistanceAndTime(result) {
let totalDistance = 0;
let totalTime = 0;
while (result.length > 1) {
const getEdgeDistanceAndTime = this.getEdge(result[0], result[1]);
totalDistance += getEdgeDistanceAndTime.distance;
totalTime += getEdgeDistanceAndTime.time;
result.shift();
}
return { totalDistance, totalTime };
}
github.com/intae92/woowacourse-precourse/commit/45279c106c696da02c55d9f270f496ab1d6c95bd
'우아한테크코스 > 우아한테크코스3' 카테고리의 다른 글
우아한테크코스 3기 프리코스 최종 미션(9) - 회고 (0) | 2021.01.10 |
---|---|
우아한테크코스 3기 프리코스 최종 미션(8) - View-ResultView.js (0) | 2021.01.09 |
우아한테크코스 3기 프리코스 최종 미션(6) - View (0) | 2021.01.08 |
우아한테크코스 3기 프리코스 최종 미션(5) - App 설정 (0) | 2021.01.08 |
우아한테크코스 3기 프리코스 최종 미션(4) - 데이터초기설정 (0) | 2021.01.08 |