albatrosary's blog

UI/UXとエンタープライズシステム

Todos in Angular2 for JavaScript

前回の続きで今回はTodosを作ってみる。Todosはいたるところで書かれているので「Hello World」的には良いかと思う。普通に書き進めるのもどうかなと思うのでAngular1で書いたTodosをAngular2に書き換える感じで記載する。UIとしてはBootstrapを利用しています。

Todos in Angular1

コントローラーとHTMLはだいぶ前に書いたものを利用します。

(component/todo/todo.html)

<h2>Todo</h2>
<!-- Todos input -->
<form role="form" ng-submit="todo.addTodo()">
  <div class="input-group">
    <input type="text" ng-model="todo.item" placeholder="What needs to be done?" class="form-control">
    <span class="input-group-btn">
      <input type="submit" class="btn btn-primary" value="Add" name="add">
    </span>
  </div>
</form>
<hr>
<!-- Todos list -->
<div>
  <p class="input-group" ng-repeat="data in todo.todoList track by $index">
    <input type="text" ng-model="data" class="form-control">
    <span class="input-group-btn">
      <button class="btn btn-danger" ng-click="todo.removeTodo($index)" aria-label="Remove">X</button>
    </span>
  </p>
</div>

JavaScriptはJohnpapaに従う

github.com

(component/todo/todo.js)

(function () {
  'use strict';

  angular
    .module('TodoApp.components.todo', [])
    .controller('TodoController', TodoController);

  TodoController.$inject = [];

  var vm;

  function TodoController() {
    vm = this;
    vm.todoList = [];
  }

  TodoController.prototype.addTodo = function () {
    vm.todoList.push(vm.item);
    vm.item = '';
  };

  TodoController.prototype.removeTodo = function (index) {
    vm.todoList.splice(index, 1);
  };
})();

ルーターやindex.htmlもありますのでgithubを確認してください。

GitHub - albatrosary/Angular1Study at step5: Comprehensive Beginner’s Guide to Angular

Todos in Angular2

Angular1で書いたTodosをAngular2に書き換えます。HTMLは

  • todo. を削除
  • ng-submit -> (ngSubmit)
  • ng-model -> [(ngModel)]
  • ng-repeat -> *ngFor
  • data in todo.todoList -> #data of todoList
  • ng-model -> [value]
  • ng-click -> (click)

で変え次のようにした。この変更はなかなか大変そう。

<h2>Todo</h2>
<!-- Todos input -->
<form role="form" (ngSubmit)="addTodo()">
  <div class="input-group">
    <input type="text" [(ngModel)]="item" placeholder="What needs to be done?" class="form-control">
    <span class="input-group-btn">
      <input type="submit" class="btn btn-primary" value="Add" name="add">
    </span>
  </div>
</form>
<hr>
<!-- Todos list -->
<div>
  <p class="input-group" *ngFor="#data of todoList; #idx = index">
    <input type="text" [value]="data" class="form-control">
    <span class="input-group-btn">
      <button class="btn btn-danger" (click)="removeTodo(idx)" aria-label="Remove">X</button>
    </span>
  </p>
</div>

ngForであるがJavaScriptのfor .. infor ... ofには明確な違いがあります。想像ですが今回inからofへ変更したのはfor文であるというのもありますが、こうした背景もあるのではと勝手に思っています。

developer.mozilla.org

var arr = [ 3, 5, 7 ];
arr.foo = "hello";

for (var i in arr) {
   console.log(i); // "0", "1", "2", "foo" を出力
}

for (var i of arr) {
   console.log(i); // "3", "5", "7" を出力
}

JavaScriptはAngular1のメソッドをそのまま利用した。

(function(app) {
  var vm;
  
  function Todo() {
    vm = this;
    this.todoList = [];
  }

  Todo.prototype.addTodo = function () {
    vm.todoList.push(vm.item);
    vm.item = '';
  };

  Todo.prototype.removeTodo = function (index) {
    vm.todoList.splice(index, 1);
  };
  
  app.TodoComponent =
    ng.core
      .Component({
        selector: 'app-todo',
        templateUrl: 'components/todo/todo.html'
      })
      .Class({
        constructor: Todo
      });
})(window.app || (window.app = {}));

ルータ等あるので完全なコードはgithubを見て下さい

最後に

Todosくらいだとプロジェクトコードを書き換えるのとはわけが違いますが、概ねHTMLをAngular1からAngular2へ書き換えるのは大変そう。Angular1のControllerをAngular2のComponentに書き換えるのはJohnpapaのようなスタイルに従っていれば楽そうかな。