カテゴリー別アーカイブ: javascript

AngularJSでUI BootstrapのTooltipをValidationに連動させて表示させる

| コメントをどうぞ

AngularJSには強力なフォームのバリデーション機能があり、任意のタイミングでエラーメッセージを表示することができます。
このエラーメッセージをバリデーションの状態に連動してUI BootstrapのTooltipに表示したいとき、どうすればよいでしょうか。

まずは思い付く方法で

まずは最初に思い付いた方法で実装してみます。
ツールチップはtooltip-enableディレクティブで有効/無効を切り替えられるので、バリデーションに失敗したときだけ有効にして表示するようにしてみました。

index.html

...

<form name="form" style="width:500px;" ng-class="{'has-error': form.value1.$dirty && form.value1.$invalid}">
  <table class="table">
    <tr>
      <th>お名前(20文字まで)</th>
      <td>
        <input type="text" class="form-control input-sm" name="value1" ng-required="true" ng-model="value1" tooltip="20文字以下で入力して下さい" tooltip-enable="form.value1.$dirty && form.value1.$invalid" ng-maxlength="20">
      </td>
    </tr>
  </table>
</form>

...

app.js

angular.module('app', ['ui.bootstrap']);

結果

バリデーションエラー時にinputにマウスカーソルを乗せることでツールチップが表示されるようになりました。

tooltip1

しかし、これではinputにマウスカーソルを乗せるまでエラーの内容が分かりませんし、マウスカーソルを離すとツールチップが消えてしまうのでイマイチです。
これは、ツールチップの表示を切り替えるデフォルトのトリガーイベントがmouseenter/mouseleaveとなっているためです。

tooltip.js

...

  // Default hide triggers for each show trigger
  var triggerMap = {
    'mouseenter': 'mouseleave',
    'click': 'click',
    'focus': 'blur',
    'none': ''
  };

...

.directive('tooltip', [ '$tooltip', function($tooltip) {
  return $tooltip('tooltip', 'tooltip', 'mouseenter');
}])

...

tooltipのカスタムトリガーとカスタムディレクティブで実現する

Plunker
今回はバリデーションの状態変化に応じて自動的にツールチップを表示したいので、自由に使えるカスタムトリガーが必要になります。

まずは、適当なconfigセクションで$tooltipProvider.setTriggers()を使ってカスタムトリガーを定義しましょう。$tooltipProvider.setTriggers()の引数には、表示イベント名をプロパティ名、非表示イベントをそのプロパティの値として持つオブジェクトを指定します。

app.js


var app = angular.module('app', ['ui.bootstrap', 'app.directives']);

// 追加
app.config(['$tooltipProvider', function ($tooltipProvider) {
  $tooltipProvider.setTriggers({
    'show': 'hide'
  });
}]);

これで要素がshowイベントを受け取った時にツールチップが表示されるようになりました。

次に、このトリガーを発火するための仕組みを作ります。

AngularJSのバリデーション機能は、バリデーション対象として指定したモデルの値の変化に応じてリアルタイムに実行され、実行結果がスコープにセットされるようになっています。上記index.htmlの例だと、form.value1.$invalidform.value1.$validのboolean値を読むことでバリデーションの状態を取得することができます。

今回はtooltipディレクティブを拡張するカスタムディレクティブを用意して、その中でform.value1.$invalidを監視することで、バリデーションの状態が切り替わった時にshowイベントまたはhideイベントを発生させてツールチップの表示を切り替えるようにしました。

directives.js


angular.module('app.directives', [])

// ツールチップ本体に付加されるディレクティブ
// デフォルトのものをそのまま流用
.directive( 'myTooltipPopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/tooltip/tooltip-popup.html'
  };
})

// tooltipディレクティブを拡張するカスタムディレクティブ
.directive('myTooltip', ['$tooltip', '$timeout', function ($tooltip, $timeout) {
  // tooltipのインスタンスを作成する
  var tooltip = $tooltip( 'myTooltip', 'myTooltip', 'show' );
  var originalCompile = angular.copy(tooltip.compile);
  tooltip.scope = {myTooltipShow : "&"}

  // compileを拡張
  tooltip.compile = function(element, attrs, scope){
    // オリジナルのLink function
    var originalLink = originalCompile(element, attrs);

    // linkを拡張
    var link = function(scope, element, attrs) {
      // my-tooltip-show属性の値を監視する
      scope.$watch(scope.myTooltipShow, function (val) {
        if (val) { // 評価値がtrueならばshowイベントを発生させる
          $timeout(function() {
            element.triggerHandler('show');
          });
        }else{ // 評価値がfalseならばhideイベントを発生させる
          $timeout(function() {
            element.triggerHandler('hide');
          });
        }
      });
      // オリジナルのlinkを実行する
      originalLink(scope, element, attrs);
    }
    return link;
  }
  return tooltip;
}])

index.html

...

<input type="text" class="form-control input-sm" name="value2" ng-required="true" ng-model="value2" my-tooltip-show="form.value2.$dirty && form.value2.$invalid" my-tooltip="20文字以下で入力して下さい" ng-maxlength="20">

...

これで、バリデーションの状態がエラーになった時点でツールチップが表示され、正常になった時点で非表示になるようになりました。
my-tooltip-showform.value2.$dirtyを加えているのは初期状態でツールチップが表示されるのを抑制するためです。

今回作成したものはPlunkerにデモを用意していますので、ご利用ください。
http://plnkr.co/edit/ynywEEpNvlx0iSA2bUpI?p=preview

Angular.jsで、アップロードするファイルをcontrollerでも使えるようdirectiveを自作する

| コメントをどうぞ

ちまたにはAngular.jsのファイルアップロードのモジュールがたくさんあるのですが、シンプルで単機能なものが欲しく、自作しました。
ファイルの内容が、

<input type="file"> → directiveのchangeイベント → controller

の順で渡るところのコードです。
controllerでその後サーバーにアップロードするところは省きます。

前提のコード

下記のように、ファイルをアップロードするコードがあるとします。
index.htmlの中で、upload.htmlをincludeしています。
upload.htmlの中ではmy-sectionというdirectiveをtranscludeで使い、またtype=”file”のinputタグがあります。
続きを読む

ウィンドウのサイズを変えていないのに window.resize イベントが発生する

| コメントをどうぞ

IE8で、ウィンドウの大きさを変えていないのに window.resize イベントが発生することがあります。

再現方法

ドキュメント内で要素の高さを変更するだけで再現します。

以下、サンプルHTMLです。

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <script>
    function resized(e){
      alert("window resized!");
    }
    function doResize(){
      document.getElementById("field").style.height = "100px"
    }
    if (window.addEventListener) {
      window.addEventListener("resize", resized, false);
    }
    else {
      window.attachEvent("onresize", resized);
    }
    </script>
  </head>
  <body style="background-color:green;">
    <input type="button" id="doResize" value="ResizeTest" onclick="doResize()">
  <div id="field" style="background-color:#000000;color:#FFF;">リサイズテスト</div>
  </body>
</html>

続きを読む

リアルタイム・バックエンドサービス「Firebase」を使ったWebアプリ作成

| 2件の返信

Firebaseは、チャットのようなリアルタイム性の高いアプリを作る際に、端末とサーバー間、端末同士でのデータ同期などのバックエンドで行う処理をAPI提供してくれる便利なバックエンドサービスです。用途としては、複数人でのリアルタイムコミュニケーションアプリやモバイルアプリのオフライン対応などが多いそうです。

まずは試しにということで、Firebaseを使ってグループテキストチャットのサンプルを作成してみましたので、Firebaseの使い方についてご紹介したいと思います。

続きを読む

Grunt の同名タスクをファイル分割する

| コメントをどうぞ

12月ですね。
12月と言えば、そう私たち会社人にとって避けては通れない忘年会のシーズンですね。
γ-GTPの上昇には気をつけて!

・・・くりすます?
なんですかそれは?

どうもDiceK Mikamiです。
デジャブ?

ここ最近はGruntを使ってグルグルしています。
(@д@)←こんな状態。
なので、Gruntに関して書いてみたいと思います。
続きを読む

AngularJS の ng-grid を動的に変化させてみる

| コメントをどうぞ

12月ですね。
12月と言えば、そう私たち会社人にとって避けては通れない忘年会のシーズンですね。
肝臓には気をつけて!

・・・くりすます?
なんですかそれは?

どうもDiceK Mikamiです。

今日はAngularUIのひとつであるng-gridを動的に変更させる方法について書いてみます。
続きを読む

Google Apps Scriptでお手軽RSS配信サービスを作る

| コメントをどうぞ

Google Apps Scriptで簡単なRSS配信サービスを作ってみました。

仕様

  • スプレッドシートを読み込み、行データを RSS の item 要素として出力
  • RSSタイトルはスプレッドシート名を利用
  • XML出力はテンプレートを利用(出力内容をカスタマイズ可能に)

続きを読む

Google Apps Script でガジェットを作成してみる

| コメントをどうぞ

前回に引き続きGoogle Apps Script活用のお話ですが、今回はGoogle Apps Scriptを使って簡単にガジェットを作成してみたいと思います。

Google Apps Scriptで作成したWebアプリをそのままinfoScoopにガジェットとして表示できたら便利ですが、X-Frame-OptionsというHTTPレスポンスヘッダにより他のサイトに直接表示することができないようになっています。クリックジャッキング対策のためだそうです。

x-frame-options:SAMEORIGIN

そこでJSONP(JSON with padding)の仕組みを使って、Googleカレンダーのイベントをガジェットに表示してみたいと思います。

続きを読む

Google Apps ScriptでSalesforceのイベント一覧を出力してみる

| コメントをどうぞ

前回の記事に引き続きGoogle Apps Scriptのサンプル作成ということで、今回はGoogle Apps ScriptからSalesforceのAPIを実行し、自分に関連するイベントリストをスプレッドシートに出力してみたいと思います。

続きを読む