FE코크
탄산 가득 시원한 개발일지
FE코크
전체 방문자
오늘
어제
  • 분류 전체보기 (43)
    • 우아한테크코스 (22)
      • 우아한테크코스4기 (4)
      • 우아한테크코스3 (10)
      • 회고록 (8)
    • Web (0)
      • HTTP 웹 기본지식 (0)
    • JavaScript (2)
    • React.js (12)
    • 알고리즘 풀이 (2)
    • HTML, CSS (4)
    • 기타 (1)
      • 일상 (0)
      • 후기 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 리액트
  • react.js
  • JavaScript
  • 우테코
  • prop drilling
  • state
  • 자바스크립트
  • CSS
  • 노마드코더
  • 코어자바스크립트
  • React.DOM
  • 우테코4기
  • 재택하고싶은데
  • 알고리즘
  • 회고록
  • jsx
  • 우아한테크코스
  • 프리코스
  • 4기
  • 개발자
  • 회고
  • 주간회고
  • 백준
  • Props
  • react
  • 레벨1회고
  • Reactjs
  • createRoot
  • 프론트엔드
  • 우아한테크코스 3기

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
FE코크

탄산 가득 시원한 개발일지

우아한테크코스 3기 프리코스 최종 미션(7) - View-InputView.js
우아한테크코스/우아한테크코스3

우아한테크코스 3기 프리코스 최종 미션(7) - View-InputView.js

2021. 1. 8. 21:26

class InputView

전에 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>
    `;
  }
}

라디오 버튼 동적으로 속성 바꾸기

<input type="radio" checked="check">

 

라디오 버튼을 클릭하면 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

 

feat: 최단거리 최소거리 구하기 · intae92/woowacourse-precourse@45279c1

Permalink This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. Browse files feat: 최단거리 최소거리 구하기 Loading branch information Showing 1 changed file with 33 additions and 0 del

github.com

 

'우아한테크코스 > 우아한테크코스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
    '우아한테크코스/우아한테크코스3' 카테고리의 다른 글
    • 우아한테크코스 3기 프리코스 최종 미션(9) - 회고
    • 우아한테크코스 3기 프리코스 최종 미션(8) - View-ResultView.js
    • 우아한테크코스 3기 프리코스 최종 미션(6) - View
    • 우아한테크코스 3기 프리코스 최종 미션(5) - App 설정
    FE코크
    FE코크
    공부한 내용을 적는 블로그

    티스토리툴바