LoginSignup
3
3

More than 5 years have passed since last update.

Twitterクライアントでつぶやく(form編) 1/2

Posted at

いつも説明が長ったらしくなる傾向にあるので、今回こそは要点だけスパスパッとかいつまんで書いてみます。

angularjs で Twitter クライアントを作成し AWS.S3 で動かす
Twitterクライアントにプロフィールページを追加
の続きです。

プロフィール画面まで作ってあるブランチはこちら

やりたいこと

  • Twitterクライアントでつぶやく
    • formを使う
    • バリデーションとか
  • 投稿結果をダイアログで表示してみる

最終的にこうなります。

tweet.gif

サービス追加

投稿機能を twitterService に追記します。

mytwitter/app/scripts/services.js
postTweet: function(message) {
    var deferred = $q.defer(),
        url = '/1.1/statuses/update.json',
        params = {
            data: {
                status: message
            }
        };

    authResult.post(url, params)
        .done(function(result) {
            deferred.resolve(result);
        }).fail(function(err) {
            deferred.reject(err);
        });
    return deferred.promise;
}

ルート作成

いつもどおり新しいルートを作成し、ナビを追加します。

$ yo angular:route tweet
index.html
<div class="collapse navbar-collapse" id="js-navbar-collapse">

    <ul class="nav navbar-nav">
        <li><a href="#/">Home</a></li>
        <li><a ng-href="#/profile">Profile</a></li>
        <li><a ng-href="#/tweet">Tweet</a></li>
        <li><a ng-href="#/about">About</a></li>
        <li><a ng-href="#/">Contact</a></li>
    </ul>
</div>

追加したら grunt serve で動作確認することをお勧めします。

投稿画面作成

モジュール追加

以下のモジュールを追加します。

  • angular-messages(フォームのメッセージ表示)
  • angular-bootstrap(bootstrap コンポーネントのディレクティブを扱う)
$ bower install angular-messages angular-bootstrap --save

モジュール参照を app.js に追加します。

mytwitter/app/scripts/app.js
angular
    .module('mytwitterApp', [
        'ngAnimate',
        'ngCookies',
        'ngResource',
        'ngRoute',
        'ngSanitize',
        'ngTouch',
        'mytwitterApp.services',
        'ngMessages',
        'ui.bootstrap'
    ])

画面作成

前回のように layoutit で粗方の HTML を作成し、ディレクティブを記述します。

mytwitter/app/views/tweet.html
<div class="container-fluid">
    <div class="row">
        <div class="col-md-12" ng-show="tweet.showTweet">
            <form class="well" name="tweetForm" ng-submit="tweet.submit()" novalidate role="form">
                <div class="form-group">
                    <label for="tweet">Tweet Text</label>
                    <textarea class="form-control" name="tweet" ng-model="tweet.inputText" placeholder="tweeeeeeeeeeeeeeeeeeet"></textarea>
                </div>
                <button class="btn btn-primary" type="submit">つぶやく</button>
            </form>
        </div>
    </div>
</div>

submit 時の振る舞いは form タグ内に ng-submit で記述する方法と、submit ボタンに ng-click で記述する方法があります。両方に書くと多重実行してしまう恐れがあるため、どちらかに書きましょう。

バリデーションとボタン制御

Twitter クライアントなので、0 文字と 140 文字を超える入力をエラーにしたいです。テキストエリアに入力上限 ng-maxlength と 必須 ng-required を追加します。

mytwitter/app/views/tweet.html
<textarea class="form-control" name="tweet" ng-maxlength="140" ng-model="tweet.inputText" ng-required="true" placeholder="tweeeeeeeeeeeeeeeeeeet"></textarea>
<div ng-if="tweetForm.tweet.$dirty" ng-messages="tweetForm.tweet.$error" role="alert">
    <div ng-message="required">入力は必須です。</div>
    <div ng-message="maxlength">入力は140文字までです。</div>
</div>

form ディレクティブはテキストエリアのバリデーション結果を tweetForm.tweet.$error に格納します。ng-messages$error の内容に基づき出力するメッセージを選択するディレクティブです。
参考:https://docs.angularjs.org/api/ngMessages
メッセージの <div> タグに ng-if="tweetFrom.tweet.$dirty" を指定しているのは、値変更時のみバリデーション結果を表示したいからです。画面表示直後に必須入力のエラーが表示されたらイヤですもの。

ng-disabled でフォームの入力が有効な場合のみ「つぶやく」ボタンを有効にします。

mytwitter/app/views/tweet.html
<button class="btn btn-primary" ng-disabled="tweetForm.$invalid" type="submit">つぶやく</button>

tweetForm.$invalid は、フォームの入力に不備がある場合のみ true が入っているため、ここでは、テキストエリアが未入力または 140 文字を超える入力がある場合は「つぶやく」ボタンが押下不可になるわけです。今回は入力コンポーネントが1つですが、複数ある場合に便利ですね。

tweet.html は以下のようになります。

mytwitter/app/views/tweet.html
<div class="container-fluid">
    <div class="row">
        <div class="col-md-12" ng-show="tweet.showTweet">
            <form class="well" name="tweetForm" ng-submit="tweet.submit()" novalidate role="form">
                <div class="form-group">
                    <label for="tweet">Tweet Text</label>
                    <textarea class="form-control" name="tweet" ng-maxlength="140" ng-model="tweet.inputText" ng-required="true" placeholder="tweeeeeeeeeeeeeeeeeeet"></textarea>
                    <div ng-if="tweetForm.tweet.$dirty" ng-messages="tweetForm.tweet.$error" role="alert">
                        <div ng-message="required">入力は必須です。</div>
                        <div ng-message="maxlength">入力は140文字までです。</div>
                    </div>
                </div>
                <button class="btn btn-primary" ng-disabled="tweetForm.$invalid" type="submit">つぶやく</button>
            </form>
        </div>
    </div>
</div>

angularjs はフォームを作成すると内部的にコントローラを作成します。フォーム内のコンポーネントには formのname属性.コンポーネントのname属性 でアクセスします。フォームはいろいろな情報を持っています。ng-inspector(Chromeプラグイン)を使えば、スコープ内の要素、関数を参照可能です。べんり。

ng.png

CSS

入力に NG がある場合にコンポーネントをピンクにしてみましょう。ナウい感じになります。

mytwitter/app/styles/main.css
form .ng-invalid.ng-dirty {
  background-color: lightpink;
}
form .ng-valid.ng-dirty {
  background-color: lightcyan;
}

コントローラ作成

TweetCtrl を作成します。

mytwitter/app/scripts/controllers/tweet.js
'use strict';

function TweetController(twitterService) {
    var vm = this;
    vm.inputText = '';
    vm.showTweet = false;

    twitterService.initialize();
    if (twitterService.isReady()) {
        vm.showTweet = true;
    }

    vm.submit = function() {
        twitterService.postTweet(vm.inputText)
            .then(function(result) {
                console.log(result);
                alert('Twitter投稿完了!');
            }, function(err) {
                console.log(err);
                alert('Twitter投稿に失敗しました。');
            });
    };
}

angular.module('mytwitterApp')
    .controller('TweetCtrl', TweetController);

Twitterへの投稿ができました! :clap:
では、投稿結果画面作ります。

と思ったけど、やっぱり長くなっちゃったので次回に続きます。。。Orz

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3