티스토리 뷰


https://docs.angularjs.org/tutorial/step_07

AngularJS에 Routing 기술과 멀티 뷰에 대한 튜토리얼입니다. 튜토리얼 정리는 모두 angularjs.org 홈페이지의 내용을 바탕으로 진행하였습니다.


AngularJS에서 Routing은 URL을 구분하여, 뷰를 변경하는 기술입니다.

AgnularJS routing 은 ngRoute 라고 요약해서 부르고, 튜토리얼을 따라하면, npm이 설치 되있으므로, 아래와 같이 명령어로 설치가 가능합니다. ( 튜토리얼에서 bower.json에 추가하여 bower install을 사용하도록 하는데 이상하게 버전을 제대로 찾이 못하여 설치가 되지않았습니다. 하여 npm을 이용하였습니다.)

npm install angular-route

angular-route가 설치가 되면, 먼저 angular.js 밑에 링크를 걸어줍니다.

ngRoute를 진행하면서, Index.html의 내용은 List부분과 Detail 부분으로 나누어 뷰를 생성할 것이기 때문에

partials 폴더 밑에 phone-detail.html과 phone-list.html을 생성합니다.

index.html의 body의 내용은 phone-list.html에 모두 옮기시고 angular-route.js 링크와 함께 아래 소스처럼 변경되었습니다.

<!doctype html> <html lang="en" ng-app="phonecatApp"> <head> <meta charset="utf-8"> <title>Google Phone Gallery</title> <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css"> <link rel="stylesheet" href="css/app.css"> <script src="bower_components/angular/angular.js"></script> <script src="bower_components/angular-route/angular-route.js"></script> <script src="js/app.js"></script> <script src="js/controllers.js"></script> </head> <body> <div ng-view></div> </body> </html>

그리고 phone-list.html의 내용은 다음과 같습니다.

    <div class="container-fluid">
        <div class="row">
            <div class="col-md-2">
                <!--Sidebar content-->
                Search:
                <input class="form-control input-sm" ng-model="query">
                Sort by:
                <select ng-model="orderProp" class="form-control" input-sm>
                    <option value="name">Alphabetical</option>
                    <option value="age">Newest</option>
                </select>
            </div>

            <div class="col-md-10">
                <!--Body content-->
                <div class="media" ng-repeat="phone in phones | filter:query | orderBy:orderProp">
                    <a class="media-left" href="#/phones/{{phone.id}}">
                        <img class="pull-left thumbnail" ng-src="{{phone.imageUrl}}" width="100" height="100">
                    </a>
                    <div class="media-body" style="padding : 10px;">
                        <h4 class="media-heading"><a href="#/phones/{{phone.id}}">{{phone.name}}</a></h4>
                        <p>{{phone.snippet}}</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

페이지만 구분되었을 분 소스의 변경은 크게 없습니다. 다만 다른 점이 있다면 index.html에서 phone-list.html의 내용이 제거되었고, 제거된 부분에 <div ng-view></div> 가 추가되었습니다.

리다이렉팅을 통해 ng-view 부분에 내용이 씌어질 것입니다.

설정 부분의 경우에도 기능에 따라 나누기 위해 전과 다르게 Provider와 config 설정은 app.js 로 옮기고

각 컨트롤러에 대한 부분은 controller.js를 이용하겠습니다. 파일을 나눌 경우 두 js 역시 ng, ngRoute js파일 아래에 링크 추가해주셔야합니다.

app.js의 소스는 다음과 같습니다.

/* App Module */ var phonecatApp = angular.module('phonecatApp', [ 'ngRoute', 'phonecatControllers' ]); phonecatApp.config(['$routeProvider', function ($routeProvider) { $routeProvider. when('/phones', { templateUrl: 'viewPage/phone-list.html', controller: 'PhoneListCtrl' }). when('/phones/:phoneId', { templateUrl: 'viewPage/phone-detail.html', controller: 'PhoneDetailCtrl' }). otherwise({ redirectTo: '/phones' }); }]);

ng-app을 초기화 하기 위해 먼저, App Module을 생성해야합니다. 상단의 'phonecatApp'이라는 이름으로 생성합니다. 여기서 ngRoute와 phonecatControllers 서비스를 추가하여, App에서 사용할 서비스를 등록합니다.

이 phonecatApp이라는 ng App 에서 ngRoute 기능과 phonecatControllers 서비스를 사용한다는 의미입니다.

.config() 는 provider에 대한 설정을 하는 부분입니다. $routeProvider 는 route의 설정파일을 정의하는 서비스입니다.

$의 의미는 ng 서비스를 의미합니다.

$는 ng에서 제공하는 서비스를 뜻하고, 사용자가 추가적으로 서비스를 생성하여 커스텀 서비스도 생산하여쓸수 있습니다. ( 이는 나중에 내용을 다루도록 하겠습니다. )

$routeProvider에서 when 와 otherwise 사용되었습니다.

현재 index.html에서 시작하여 /phones라는 url이 입력될 경우 viewPage폴더안에 phone-list.html을 읽어온다는 의미이며, controller 설정에 의해 phone-list.html에서 표시될 데이터를 정의할 수 있습니다.

두번째 when에서는 /phones/:phoneId 로 :phoneId는 route Parameter가 될 부분으로 임시 데이터의 키값이 될 것입니다. 이는 자세한 데이터를 보기 위해 키값이 필요한 것과 비슷한 맥락이라고 보시면 됩니다.

페이지는 phone-detail.html이고, PhoneDetailCtrl이라는 컨트롤에서 데이터가 정의 될 것입니다.

otherwise는 when으로 정의된 url 외는 모두 /phones란 url로 redirect 시키라는 의미입니다. 그러므로 현재 예제에서는 /phones 와 /phones/:phoneId 이 두가지 url 만 접근 할 수 있습니다.

그럼 다음은 controller.js 입니다.

/* Controllers */ var phonecatControllers = angular.module('phonecatControllers', []); phonecatControllers.controller('PhoneListCtrl', ['$scope', '$http', function($scope, $http){ $http.get('phones/phones.json').success(function(data){ $scope.phones = data; }); $scope.orderProp = 'age'; }]); phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams','$http', function($scope,$routeParams,$http){ $http.get('phones/' + $routeParams.phoneId + '.json').success(function(data){ $scope.phone = data; $scope.mainImageUrl = data.images[0]; }); }]);

phoneControllers라는 변수를 선언하고, 변수명을 인자값에 추가합니다. 이 이름은 app.js에서 app을 정의할 때 추가한 controller 이름과 동일해야합니다. 

app.js 에서 2개의 view에 대한 컨트롤이 두개였으므로, 두개의 컨트롤에 대한 내용이 작성되어있습니다.

위에는 PhoneListCtrl 로써 $http를 사용하여, 서버(예제는 임시)로부터 JSON으로 데이터를 리턴받았습니다.

$scope 서비스는 ng-app으로써 선언된 application model과 관련된 서비스입니다. 

$http.get().success(data) 에서 data를 $scope.phones에 저장하였으니, 데이터는 ng-app 전체에서 사용할 수 있게 되었습니다.

결과값(JSON)에는 age,id,imageUrl,name,snippet으로 구성된 정보이고, phone-list.html 에서 이를 출력합니다.

두번째 컨트롤러에서는 조금 다르게 $routeParams가 있습니다.

phone-list.html에서 각각의 상품의 상세정보를 볼 수 있도록 링크 설정을

href="phones/id" 이런식으로 정의해놓았고, ngRoute에서 정의했듯이 뒤에 id는 route Parameter로 구분하게 되어 사용할 수 있습니다.

각각의 상품명에 대해서는 이 예제에서 JSON 파일로 모두 가지고 있기 때문에(파일명이 아이디와 동일)

$http.get()메소드를 사용하여, 상세 정보를 읽어들여서 상세 정보를 출력하게 됩니다.

아래는 phone-detail.html 내용입니다.

<div class="container">
    <div class="media">
        <div class="media-left">
            <img class="pull-left img-thumbnail" ng-src="{{mainImageUrl}}" style="margin:0 20px 20px 0;">
        </div>
        <div class="media-body" style="padding-top:30px;">
            <h1 class="media-heading">{{phone.name}}</h1>
            <p>{{phone.description}}</p>
            <ul class="list-inline">
                <li ng-repeat="img in phone.images">
                    <a href="" ng-click="setImage(img)"><img class="thumbnail" ng-src="{{img}}" width="100" height="100"></a>
                </li>
            </ul>
            <div class="col-sm-4"><input type="text" class="form-control input-sm" ng-model="name2"></div>
            <button class="btn btn-sm btn-primary"ng-click="hello(name2)">Hello</button>
        </div>
    </div>

    <div class="row">
        <div class="col-sm-3">
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Availability and Networks</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>Availability</dt>
                        <dd ng-repeat="availability in phone.availability">{{availability}}</dd>
                    </dl>
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Android</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>OS Version</dt>
                        <dd>{{phone.android.os}}</dd>
                        <dt>UI</dt>
                        <dd>{{phone.android.ui}}</dd>
                    </dl>
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Camera</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>Primary</dt>
                        <dd>{{phone.camera.primary}}</dd>
                        <dt>Features</dt>
                        <dd>{{phone.camera.features.join(', ')}}</dd>
                    </dl>
                </div>
            </div>
        </div>
        <div class="col-sm-3">
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Battery</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>Type</dt>
                        <dd>{{phone.battery.type}}</dd>
                        <dt>Talk Time</dt>
                        <dd>{{phone.battery.talkTime}}</dd>
                        <dt>Standby time (max)</dt>
                        <dd>{{phone.battery.standbyTime}}</dd>
                    </dl>
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Size and Weight</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>Dimensions</dt>
                        <dd ng-repeat="dim in phone.sizeAndWeight.dimensions">{{dim}}</dd>
                        <dt>Weight</dt>
                        <dd>{{phone.sizeAndWeight.weight}}</dd>
                    </dl>
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Additional Features</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dd>{{phone.additionalFeatures}}</dd>
                </div>
            </div>
        </div>
        <div class="col-sm-3">
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Storage and Memory</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>RAM</dt>
                        <dd>{{phone.storage.ram}}</dd>
                        <dt>Internal Storage</dt>
                        <dd>{{phone.storage.flash}}</dd>
                    </dl>
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Display</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>Screen size</dt>
                        <dd>{{phone.display.screenSize}}</dd>
                        <dt>Screen resolution</dt>
                        <dd>{{phone.display.screenResolution}}</dd>
                        <dt>Touch screen</dt>
                        <dd>{{phone.display.touchScreen | checkmark}}</dd>
                    </dl>
                </div>
            </div>
        </div>
        <div class="col-sm-3">
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Connectivity</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>Network Support</dt>
                        <dd>{{phone.connectivity.cell}}</dd>
                        <dt>WiFi</dt>
                        <dd>{{phone.connectivity.wifi}}</dd>
                        <dt>Bluetooth</dt>
                        <dd>{{phone.connectivity.bluetooth}}</dd>
                        <dt>Infrared</dt>
                        <dd>{{phone.connectivity.infrared | checkmark}}</dd>
                        <dt>GPS</dt>
                        <dd>{{phone.connectivity.gps | checkmark}}</dd>
                    </dl>
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title"><strong>Hardware</strong>
                    </div>
                </div>
                <div class="panel-body">
                    <dl>
                        <dt>CPU</dt>
                        <dd>{{phone.hardware.cpu}}</dd>
                        <dt>USB</dt>
                        <dd>{{phone.hardware.usb}}</dd>
                        <dt>Audio / headphone jack</dt>
                        <dd>{{phone.hardware.audioJack}}</dd>
                        <dt>FM Radio</dt>
                        <dd>{{phone.hardware.fmRadio | checkmark}}</dd>
                        <dt>Accelerometer</dt>
                        <dd>{{phone.hardware.accelerometer | checkmark}}</dd>
                    </dl>
                </div>
            </div>
        </div>
    </div>
</div>
처음 접하고 있는 angularjs 를 공식 홈페이지에서 튜토리얼을 보며 공부하고있습니다. 많은 질타와 지적 부탁드립니다.

댓글